1.15.2 Save & load runnable connected to an item

Discussion in 'Spigot Plugin Development' started by 6u5t4v, Jan 19, 2020.

  1. I am create a feature where when you activate a custom item, then some effects are added to the player, while also starting a timer (this works great)

    Problem
    If the player with an activated item leaves, causes the timer to be remove and when he joins again the item is not usuable anymore, because the check that checks if the item has a cooldown never gets cleared.

    Achieve
    I dont want to remove the cooldown of the item when the players leaves because I want the cooldown to continue from where it left of.

    Current code snippets
    Cooldown object is created when a new object of it is created, and then it stops itself after the timer runs out
    Code (Java):

    private class ItemCooldown implements Runnable {
            private BukkitTask toCancel;
            private double cooldown;
            private ItemStack item;
            private Pet pet;
         
            public ItemCooldown(ItemStack item, Pet pet, double cooldown) {
                this.item = item;
                this.cooldown = cooldown;
                this.pet = pet;
            }

            @Override
            public void run() {
                ItemMeta meta = item.getItemMeta();
                meta.setDisplayName(Lang.chat("&7On cooldown &e" + cooldown));
                item.setItemMeta(meta);
                cooldown -= 0.1;
    //            Debug.log("cooldown: " + cooldown);
                if (cooldown <= 0) {
                    meta.getCustomTagContainer().setCustomTag(plugin.wrapper.onCooldownKey, ItemTagType.STRING, "false");
                    meta.setDisplayName(Lang.chat(plugin.wrapper.getDisplayname(pet).replace("%cooldown%", "&a&l&nREADY")));
                    item.setItemMeta(meta);
                    petCooldown.remove(item);
                    toCancel.cancel();
                }
            }

            public void setCancelTask(BukkitTask task) {
                this.toCancel = task;
            }
        }
    The start cooldown is a method that is called when I want to start the cooldown on a itemstack, it creates the cooldown object
    Code (Java):
     
    public Set<ItemStack> petCooldown = new HashSet<>();
    public void startCooldown(ItemStack item, Pet pet) {
         
            ItemCooldown cooldown = new ItemCooldown(item, pet, 60);
            cooldown.setCancelTask(Bukkit.getScheduler().runTaskTimer(plugin, cooldown, 0, 2));
        }
     

  2. You can save the information of the cool down when the player quits from the server and apply it once he rejoin.
     
    • Like Like x 1
  3. I'll try that out, I dont know why I didnt think of that xD
     
  4. I had do something like this a bit ago, although I did it on a server-wide basis rather than for an individual player. I'll give you the code I used, just as a reference, if it's needed.

    In onDisable
    Code (Java):

            for (UUID u : moneyBoost.keySet()) {
                Files.data.set("users." + u.toString() + ".booster.boost", moneyBoost.get(u));
                Files.data.set("users." + u.toString() + ".booster.time", moneyExpire.get(u) - System.currentTimeMillis());
            }
    in onEnable
    Code (Java):

            conf = Files.data.getConfigurationSection("users");
            if (conf != null) {
                for (String s : conf.getKeys(false)) {
                    if (conf.getConfigurationSection(s + ".booster") != null) {
                        moneyBoost.put(UUID.fromString(s), conf.getDouble(s + ".booster.boost"));
                        moneyExpire.put(UUID.fromString(s), System.currentTimeMillis() + conf.getLong(s + ".booster.time"));
                        Files.data.set("users." + s + ".booster", null);
                    }
                }
            }

    Hope this helps, if you still need help that is. Please leave a positive rating if it does :)
     
  5. Thanks man, but I am trying to stick with runnables. my only issue rn is that I cant disable the runnable when the player leaves
     
  6. FrostedSnowman

    Resource Staff

    Your save method will give you a negative value.
     
  7. Strahan

    Benefactor

    Store the task ID and kill it when necessary.
     
  8. Sorry, I know this isn't relevant anymore to the question and Strahan has probably solved it for you, but I wanted to point out there's a great way of doing this in GSON which is already a part of spigot (meaning no extra dependencies!)


    Code (Java):

        public File getFile() {
            try {
                File file = new File(plugin.getDataFolder() + File.separator + "cooldowns.json");

                if (!file.exists()) {
                    file.createNewFile();
                }
                return file;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        public void save() {
            try {
                new FileWriter(getFile(), false).close();
                FileWriter fileWriter = new FileWriter(getFile());
                Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
                JsonParser jsonParser = new JsonParser();
                JsonElement jsonElement = jsonParser.parse(gson.toJson(this.cooldownMap));

                fileWriter.write(gson.toJson(jsonElement));
                fileWriter.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void load() {
            try {
                Gson gson = new Gson();
                Type type = new TypeToken<Map<UUID, Long>>() {
                }.getType();
                FileReader fileReader = new FileReader(getFile());
                Map<UUID, Long> cooldowns = gson.fromJson(fileReader, type);
                this.cooldownMap.putAll(cooldowns);
                fileReader.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    And yes it's not the prettiest code i've wrote and I shouldn't just be catching plain exception etc etc but it's just a proof of concept and it's worked really well so far. Would reccomend.