Solved Per-Player & Per-Ability cooldowns, getting ConcurrentModificationException

Discussion in 'Spigot Plugin Development' started by VivianMusic, Apr 1, 2020.

  1. I have an Ability object, with a bunch (20 subclasses). I am trying to serialize/deserialize them to a Json file. There's a problem with this because my Ability class is abstract, and I have about 20 AbilityClasses which extend it. If I try to serialize my list of Abilities (all different types), I get an error saying there isn't an adapter for that specific type.

    Edit: The scope of my issue has changed, please see my last post
     
    #1 VivianMusic, Apr 1, 2020
    Last edited: Apr 1, 2020
  2. This is what I am getting from your post:

    You can write everything to the file fine but you cannot read it. Correct me if I am wrong.

    You posted the create file method but we need to see the read code to find what might be going wrong.
     
  3. I solved that issue. Now my current issue:

    I am trying to set a cooldown for the ability
    Code (Text):
    playerCPlayer.setCooldown(this, this.getCooldownTime());
    this is my Ability class, which extends "Ability".

    I am running a cooldown ticker
    Code (Text):
        public void runCooldownTimer() {
            new BukkitRunnable() {

                @Override
                public void run() {
                    for(Ability abilities : ClassesMain.getInstance().abilityManager.getAbilityList()) {
                        for(Player allPlayers : Bukkit.getServer().getOnlinePlayers()) {
                            CPlayer playerCPlayer = ClassesMain.getInstance().cPlayerManager.getCPlayerByUUID(allPlayers.getUniqueId());

                            if(playerCPlayer.getAbilityCooldowns() == null || playerCPlayer.getAbilityCooldowns().isEmpty()) return;

                            for(Ability abilityCooldowns : playerCPlayer.getAbilityCooldowns().keySet()) {
                                int currentCooldown = playerCPlayer.getAbilityCooldowns().get(abilityCooldowns);
                                if(currentCooldown == 0) {
                                    if(allPlayers.isOnline()) {
                                        if(playerCPlayer.isInAbilityMode()) {
                                            allPlayers.getInventory().setItem(abilities.getSlotNum(), ItemUtils.addGlow(instance.classInventoryUtil.createItemForAbility(abilities.getSlotNum(), playerCPlayer.getClassType(), abilities.getName(), abilities.getLore())));
                                        }

                                        ClassUtils.sendActionBar(allPlayers, Messages.getMessage(MessageType.ABILITY_OFF_COOLDOWN).replace("{ABILITY}", abilities.getName()));
                                    }

                                    playerCPlayer.setCooldown(abilities, 0);
                                } else {
                                    if(allPlayers.isOnline()) {
                                        if(playerCPlayer != null) {
                                            if(playerCPlayer.isInAbilityMode()) {
                                                allPlayers.getInventory().setItem(abilities.getSlotNum(), ClassesMain.getInstance().classInventoryUtil.countdownPlaceholder(currentCooldown));
                                            }
                                        }
                                    }
                                    playerCPlayer.setCooldown(abilities, (currentCooldown - 1));
                                }
                            }
                        }
                    }

                    for(Player all : Bukkit.getServer().getOnlinePlayers()) {
                        CPlayer allCPlayer = ClassesMain.getInstance().cPlayerManager.getCPlayerByUUID(all.getUniqueId());

                        if(allCPlayer != null) {
                            if(allCPlayer.hasWandCooldown()) {
                                if(allCPlayer.getWandCooldownTime() >= 1) {
                                    allCPlayer.setWandCooldownTime(allCPlayer.getWandCooldownTime() - 1);
                                } else {
                                    allCPlayer.setWandCooldown(false);
                                    allCPlayer.setWandCooldownTime(0);
                                }
                            }
                        }
                    }
                }
            }.runTaskTimer(ClassesMain.getInstance(), 0, 20);
        }
    and I'm getting a ConcurrentModificationException (because I am doing
    Code (Text):
    playerCPlayer.setCooldown(abilities, (currentCooldown - 1));
    but I don't know a better way to do it. When one ability gets put on cooldown, it gives that error and sets all of their abilities on cooldown
     
  4. Solved!

    Issue: I am a dumbass
     
  5. You should consider not using a runnable at all.

    You can just mark the current time when (I think) the player uses a wand.
    If they try to cast the spell again, just check if the difference between the current time, and the time you marked down is greater than or equal to the length of the cooldown.
    Same result, you have spells with cooldowns, but without all these tasks ticking away when they really don't need to. You won't get any concurrent modification errors, and you will end up with better server performance.
     
  6. I'm setting the amount of the item in their inventory so they know how much longer is left