How to restrict natural exp level up?

Discussion in 'Plugin Development' started by CrazyYoungBro, Jun 17, 2016.

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

    CrazyYoungBro

    Hello,
    I am making a level up plugin in which I want players to level up using /level only. How can I restrict the natural exp level up?
     
  2. Offline

    Minesuchtiiii

    Just use the PlayerLevelChangeEvent and cancel it.
    When running the command do something like:

    Code:
    int lvl = e.getPlayer().getLevel();
    
    p.setLevel(lvl +1);
    to add him 1 lvl.
     
  3. Offline

    CrazyYoungBro

    I know how to level him up but I don't know how to cancel natural level up? Please explain more on that or supply code for it.
     
  4. Offline

    I Al Istannen

  5. Offline

    CrazyYoungBro

  6. Offline

    I Al Istannen

    @CrazyYoungBro
    Whoops. My bad. I though it implemented cancellable. Then you can save the current xp the player has (the even will occur before the change) in a variable and schedule a task to run a tick later and reset the xp to the saved variable. Like this:

    Code:
    event method
      final currentXp = playerXp
      schedule one tick later
        playerXp = currentXP
      end schedule
    end event method
     
  7. Offline

    Minesuchtiiii

    Code:
    e.setCancelled(true);
     
    CrazyYoungBro likes this.
  8. Offline

    I Al Istannen

    @Minesuchtiiii
    PlayerXpChangeEvent doesn't implement Cancellable. This method is undefined.
     
    CrazyYoungBro likes this.
  9. Offline

    Minesuchtiiii

    If you would have read my post you would have seen that i was talking about

    Code:
    PlayerLevelChangeEvent
     
  10. Offline

    CrazyYoungBro

    @Minesuchtiiii
    Tried it, returns error.
    The methos setCancelled(boolean) is not defined for the type PlayerLevelChangeEvent
     
  11. Offline

    I Al Istannen

    @Minesuchtiiii
    This will not work correctly for him, which is why I assumed you made an error. He can gain xp, but just not level up. Apart from that I don't even know if the event fires if you use the setLevel method. Nothing in the Javadoc.
    And, if you would have glanced at the Javadoc, the LevelChangeEvent isn't cancellable too.

    @CrazyYoungBro
    If you could look at my post again and say if it worked: here (just post number 6).
     
  12. Offline

    CrazyYoungBro

    Okay. I had a glance at it. Could you tell in which event to add it? And how to schedule the tasker to 1 tick later?
     
  13. Offline

    WolfMage1

  14. Offline

    CrazyYoungBro

  15. Offline

    I Al Istannen

    @CrazyYoungBro
    In the PlayerXpChangeEvent. For the scheduling, have a look here.

    EDIT: Ninjad... ;)
     
  16. Offline

    CrazyYoungBro

    Couldn't understand how scheduling works and hwo to implement it into my events class.
    I know what to do but not how to.
    Here is my class:
    Code:
    package me.arihant.levelup;
    
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.PlayerDeathEvent;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.event.player.PlayerExpChangeEvent;
    import org.bukkit.scheduler.BukkitTask;
    
    
    
    public class LevelUpEvents implements Listener{
       
        @EventHandler
        public void onPlayerKill(PlayerDeathEvent event) {
           
            Player killer = (Player) event.getEntity().getKiller();
           
            if(killer instanceof Player) {
                if(!(killer == null)) {
                    killer.giveExp(1);
                }
            }
                   
        }
    
        public void onXpChange(PlayerExpChangeEvent e) {
            final double currentXp = e.getPlayer().getExp();
            BukkitTask task = new LevelUpTask()
        }
       
        public static String memberPrefix = "§8[§7User§8]§7 ";
        public static String ultraPrefix = "§8[§b§lUltra§8]§7 ";
        public static String megaPrefix = "§8[§a§lMega§8]§7 ";
        public static String omegaPrefix = "§8[§c§lOmega§8]§7 ";
        public static String deltaPrefix = "§8[§f§lDel§bta§8]§7 ";
        public static String traineePrefix = "§3§lTrainee§7";
        public static String modPrefix = "§6§lMod§7 ";
        public static String srmodPrefix = "§6§lSr.Mod§7 ";
        public static String adminPrefix = "§4§lAdmin§7 ";
        public static String leaderPrefix = "§4§lLeader§7 ";
        public static String ownerPrefix = "§4§lOwner§7 ";
        public static String builderPrefix = "§9§lBuilder§7 ";
        public static String youtubePrefix = "§c§lYoutube§7 ";
       
       
        @EventHandler
        public void onChat(AsyncPlayerChatEvent e) {
           
            Player player = (Player) e.getPlayer();
            String message = e.getMessage();
            int x = player.getLevel();
            String xy = Integer.toString(x);
            String level = null;
            if(x >= 0 && x <= 19) {
                level = "§7" + xy;
            }
            else if(x >= 20 && x <= 39) {
                level = "§9" + xy;
            }
            else if(x >= 40 && x <= 59) {
                level = "§6" + xy;
            }
            else if(x >= 60 && x <= 89) {
                level = "§a" + xy;
            }
            else if(x >= 90 && x <= 99) {
                level = "§c" + xy;
            }
            else if(x == 100) {
                level = "§4" + xy;
            }
           
            if(player.hasPermission("up.member")) {
                e.setFormat(level + " " + memberPrefix + player.getName() + " §8§l>§r " + message );
            }
            else if(player.hasPermission("up.ultra")) {
                e.setFormat(level + " " + ultraPrefix + player.getName() + " §8§l>§r " + message );
            }
            else if(player.hasPermission("up.mega")) {
                e.setFormat(level + " " + megaPrefix + player.getName() + " §8§l>§r " + message );
            }
            else if(player.hasPermission("up.omega")) {
                e.setFormat(level + " " + omegaPrefix + player.getName() + " §8§l>§r " + message );
            }
            else if(player.hasPermission("up.delta")) {
                e.setFormat(level + " " + deltaPrefix + player.getName() + " §8§l>§6 " + message );
            }
            else if(player.hasPermission("up.trainee")) {
                e.setFormat(level + " " + traineePrefix + player.getName() + " §3§l>§b " + message );
            }
            else if(player.hasPermission("up.mod")) {
                e.setFormat(level + " " + modPrefix + player.getName() + " §6§l>§b " + message );
            }
            else if(player.hasPermission("up.srmod")) {
                e.setFormat(level + " " + srmodPrefix + player.getName() +  "§4§l>§b " + message );
            }
            else if(player.hasPermission("up.admin")) {
                e.setFormat(level + " " + adminPrefix + player.getName() + " §4§l>§b " + message );
            }
            else if(player.hasPermission("up.leader")) {
                e.setFormat(level + " " + leaderPrefix + player.getName() + " §4§l>§b " + message );
            }
            else if(player.hasPermission("up.owner")) {
                e.setFormat(level + " " + ownerPrefix + player.getName() + " §4§l>§b " + message );
            }
            else if(player.hasPermission("up.builder")) {
                e.setFormat(level + " " + builderPrefix + player.getName() + " §9§l>§r " + message );
            }
            else if(player.hasPermission("up.youtube")) {
                e.setFormat(level + " " + youtubePrefix + player.getName() + " §c§l>§r " + message );
            }
           
           
        }
       
    
    
    }
    
    
     
  17. Offline

    I Al Istannen

    @CrazyYoungBro
    You should redo your prefix system. The current way can surely be made better :) I might try to think of a better one.

    But to your problem (quote from the link I posted):
    Code:
            new BukkitRunnable() {
           
                @Override
                public void run() {
                    // What you want to schedule goes here
                    plugin.getServer().broadcastMessage(
                        "Welcome to Bukkit! Remember to read the documentation!");
                }
               
            }.runTaskLater(this.plugin, 20);
    Just replace the 20 with 1 and "this.plugin" with your plugin instance.
    Then do what I wrote in the 6th post. The code inside the run method will be executed a tick later.
     
  18. Offline

    CrazyYoungBro

    @I Al Istannen Instance of main class or event class?

    Here is my code:
    Code:
    public void onXpChange(PlayerExpChangeEvent e) {
            BukkitTask x = new BukkitRunnable() {
                  
                @Override
                public void run() {
                   
                   final float currentXp = e.getPlayer().getExp();
                   e.getPlayer().setExp(currentXp);
                   
                }
              
            }.runTaskLater(this.main, 1);
        }
     
  19. Offline

    I Al Istannen

    @CrazyYoungBro
    Instance of main class.
    And move the "final float currentXp" before the runnable. If you don't do this, you code will do nothing, as it sets the new xp to the new one.
     
  20. Offline

    CrazyYoungBro

    @I Al Istannen Thanks. Just a last question. How can I implement the prefix stuff in my main class.
     
  21. Offline

    I Al Istannen

    @CrazyYoungBro
    I ended up using an enum. Don't really know how I should explain that to you :/ Posting code would be the easiest, but it is dicouraged here and I don't know if you just copy-paste it.
    outline.png
    The Prefix group constructor takes three Strings. The first is the prefix, the second the suffix and the third the permission. Just add all your ranks as enum entries, and the HIGHEST rank at the top and the LOWEST at the bottom.

    Then for the getByPermission(Permissible) you just look through all the entries. This means, you will start at the highest entry. If the permissible has permission for the entry, return it. If the permissible has no right for any of the groups, return an empty Optional (or null, but the optional is better).

    Then in the onChat event, get the group for the player using the PrefixGroups#getByPermission method. If it is present (or not null), apply it. To apply it, you modify the format in the following way:
    "e.setFormat(group.getPrefix() + "%1$s" + group.getSuffix() + "%2$s")"
    The "%1$s" will automatically be replaced with the player's displayname, you don't need to do it. The "%2$s" will be replaced with the message.

    This is all.
     
  22. Offline

    CrazyYoungBro

    That is a very nice approach to the given problem. Thanks a lot for all of this.
    I did all of it.

    I have two classes. One which contains these stuff and the other which contains onCommand method. How can I implement all of the events in main class?
     
  23. Offline

    I Al Istannen

    @CrazyYoungBro
    Depends on the case. I don't know how you set your classes up, so I can't really tell. Posting these classes would make it easier. If you want to regiser an event, which is in an different class, just pass the instance of this class to Bukkit#getPluginManager()#registerEvents(class instance, Main class) in your onEnable.
     
  24. Offline

    CrazyYoungBro

    One class is set up as you said. Other is here:
    Code:
    package me.arihant.levelup;
    
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class LevelUp extends JavaPlugin{
       
       
        public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
           
            if(!(sender instanceof Player)) {
                sender.sendMessage(ChatColor.GREEN + "This command is only for players!");
                return false;
            }
           
            Player player = (Player) sender;
           
            if(cmd.getName().equalsIgnoreCase("level")) {
                if(args.length == 0) {
                    player.sendMessage(ChatColor.RED + "Usage: /<command> <player> <level>");
                    return false;
                }
                if(args.length == 1) {
                    player.sendMessage(ChatColor.RED + "Please specify a level!");
                    return false;
                }
                if(args.length > 2) {
                    player.sendMessage(ChatColor.RED + "Too many arguments!");
                }
                @SuppressWarnings("deprecation")
                Player target = Bukkit.getServer().getPlayer(args[0]);
               
                if(target == null) {
                    player.sendMessage(ChatColor.RED + "Could not find player !");
                    return false;
                }
               
                if(target.getLevel() >= 100) {
                    target.setLevel(0);
                }
                else {
                    String args2 = args[1];
                    int level = Integer.parseInt(args2);
                    target.setLevel(level);
                }
               
            }
           
            return true;
        }
    }
    
     
  25. Offline

    I Al Istannen

    @CrazyYoungBro
    So, now you want to register the listener? If so, use what I said:
    In the onEnable() method in your Main class (the one extending JavaPlugin), write this:
    Bukkit.getPluginManager().registerEvents(<the instance of the other class here. Probably "new YourOtherClass()"> this);
     
  26. Offline

    CrazyYoungBro

    Thanks. One more thing.
    This code returns errors:
    Code:
    public void onXpChange(PlayerExpChangeEvent e) {
            BukkitTask x = new BukkitRunnable() {
                 
                @Override
                public void run() {
                  
                   final float currentXp = e.getPlayer().getExp();
                   e.getPlayer().setExp(currentXp);
                  
                }
             
            }.runTaskLater(this.main, 1);
        }
    this.main is
    Code:
    public static LevelUp main;
     
  27. Offline

    I Al Istannen

    @CrazyYoungBro
    Jup. This is because "this.main" is not an instance of your main class. It must be though.
    The best way of fixing this is passing an instance of your main class through the constructor in this class and saving in a variable. Then use this variable.
     
  28. Offline

    CrazyYoungBro

    Fixed it:
    Code:
    public void onXpChange(PlayerExpChangeEvent e) {
            @SuppressWarnings("unused")
            BukkitTask x = new BukkitRunnable() {
                 
                @Override
                public void run() {
                   
                   final float currentXp = e.getPlayer().getExp();
                   e.getPlayer().setExp(currentXp);
                   
                }
               
            }.runTaskLater(LevelUpEvents.main, 1);
        }
    
    One more thing, can you tell how to check if a player has enough xp to level up. I need to check it while executing my command /level <player> <level>
     
  29. Offline

    I Al Istannen

    @CrazyYoungBro
    I wouldn't fix it that way :) I would at least make the variable "main" private and provide a public getter (getInstance()) for it.

    Experience is totally **** in bukkit. CurrentXp returns the percentage the user needs to the next level. So, just check if this value is really close to 1.
    In fact, it annoyed me so much, that I wrote a small class just to get the actual xp a player has, the level that relates to and the amount of xp the bar of the user relates to. The code isn't that fancy, nor efficient, but I can post the gist of it, if you want.
     
  30. Offline

    CrazyYoungBro

    Please do post it. I am experienced in Java but am a total newbie in Bukkit. I didn't understand from what you said about getInstance() for main.
     
Thread Status:
Not open for further replies.

Share This Page