[SOLVED] A Few Questions

Discussion in 'Spigot Plugin Development' started by HexLazer205, Jul 7, 2015.

Thread Status:
Not open for further replies.
  1. I have a few questions about a few things I'm not really sure about.

    Firstly, I'm confused as to why some people like to, on the server start, take all the config variables (such as players and their amount of money), and store those into HashMaps, then while the server is running, store everything in the HashMaps. Then on the server quit, they would put all of the HashMap's information into the configs for later use. Why do they do this? There would be a problem if there was a power outage or something related, etc. and the data wouldn't be stored because the plugin can't call the onDisable() method when it's already shut down. I would just store and get values from the config as the server is running. Also, using HashMaps would use up memory, so using configs would be better IMO.

    Also, I don't know something about the Bukkit scheduler. So, you would create a repeated task with:
    Code (Text):

    int taskid = 0;

    taskid = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
        @Override
        public void run() {
            //repeated code here...
        }
    }, ticksUntilStart, tickRepeatSpeed);
     
    And then you would create a delayed task with:
    Code (Text):

    Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
        @Override
        public void run() {
            //delayed code here...
        }
    }, ticksUntilCall);
     
    I watched a few tutorials on how to do cooldowns, and it seems they are just making a new delayed task whenever a player uses /kit or whatever they do. However, I don't understand how this would be a delayed task for just the player, and not the whole server. After thinking about it for a bit, I find out it's probably because the delayed task (inside the run method) does player.whatever() which does things for just that specific player. Done! However... what if I wanted to do a cooldown for a weapon power in a minigame or something that constantly lets the player know how much time they have left? For instance, a player shoots a wither skull from a sword, and then they can't do it until 8 seconds have passed. However, it would constantly let them know the time left in the exp bar or something, if you know what I'm saying (7, 6, 5, 4, 3, 2, 1, power enabled!). I would think I could do that easily in a repeated scheduler, however there is a problem. If there are multiple repeated schedulers running at one time, and then I try to cancel it, it won't work. I wonder if this is because multiple schedulers are running using the same integer (task id)? If that is so, then I could use a for loop to increment the integer until it is at a number that is not already being used by a repeated task, right?

    Any help/answers is appreciated. Thanks!
     
  2. Ok, people store things from configs because otherwise you would Be getting the server to access a file everytime something is being changed (accessing a file on an event run every second isnt efficient) and for the delayed tasks, make a task that runs every second and create an int name it like counter and count down every second maybe? But per player, you would have to create the int when the task is created (name it with the player UUID) then count it down like I have said
     
  3. Hi, I understand getting things from a config file every time a player does something isn't very efficient, however it's a lot safer than storing the data in memory while the server is running. I say this because if there was a power outage or anything related that forcefully shuts the computer or server down, without allowing it to go through the onDisable() method first, it would be unable to store the player information into the configs, and then data would be lost.

    Also, what do you mean "name the int with the player UUID"?
     
  4. Getting and setting to the FileConfiguration object does not save or load anything from the actual file. It merely stores data in memory. It is when you call saveConfig() that the data is saved. Keep in mind that IO operations tend to be slower than accessing memory. This is why it is preferred not to save and load to/from the file system every time a variable changes.
     
  5. I know that, but what if something like a power outage occurs that forcefully shuts the server down? That causes it to be unable to use the onDisable() method (it's already shut down), so all the player's data would be lost. What would I do then?
     
  6. Save periodically. Then at least you will have close to up-to-date data. Also keep in mind that it would be wise to do IO asynchronously. (I do not know if saveConfig handles that part for you)
     
  7. Alright, so I could create a Bukkit scheduler that would save all the data in the HashMaps to the config every 5 minutes or so.

    What about the weapon cooldowns from my original post?
     
  8. That's one way to do it, yes. As for the cooldown, there are a lot of different possible approaches to thus problem. A repeating task seems like a good choice. Why don't you give it a try and come back here if you're having trouble?
     
  9. Alright, I successfully created it while updating the exp bar every second (9, 8, 7, 6) and the player cannot shoot a wither skull when the cooldown is running. However, I'm not sure this will work for multiple players using this cooldown at one time, because the integer "taskid" would be updated every time someone uses the wither shot.

    However, I come to think that when creating the task, you're setting the integer to the task (let's say 2). Then, another player uses a new task (it goes to 3). Wouldn't the integer "2" already be with the first task?

    Also, I couldn't cancel the task this way, because Bukkit.getScheduler().cancelTask(taskid); would find the newer integer of taskid. I would create a HashMap containing an integer as the value, right?

    Here is my current code: http://hastebin.com/eqokajipij.avrasm (my indenting is 4 spaces, hastebin decided to double it for an odd reason).
     
  10. Consider using a BukkitRunnable. It has a cancel() method you can use to cancel the task. Eliminating the need to know the task ID in the first place.
     
  11. Ah, yes, that's a good idea.
     
  12. Yeah I forgot about hashmaps for a second xD, storing the cooldowns ina hashmap for each player UUID would be the way to go, and there is no need to save the hashmap to a config because a cooldown for a weapon use would be useless if the server shuts down or crashes
     
  13. @LeePMC I was asking those 2 as different questions, and they aren't related to each other. I wasn't planning on storing information about cooldowns :p

    Anyway, so far I'm doing good with this, I just need to figure out how to bring in the player instance to the BukkitRunnable class. How would I do that?

    Cooldown class (Main class):
    http://hastebin.com/oxotikigep.avrasm

    Timer class (BukkitRunnable class):
    http://hastebin.com/ovitaqobik.avrasm
     
  14. Create a mothod in the bukkit runnable class that requires the player or the player UUID (you can then use the UUID to find the player)

    Oh and its better if you put the events in different classes, (trust me its so much easier when your working with more events)
     
  15. Yeah, it's easier to split everything into multiple classes to keep your code easier to navigate, more organized, etc. but this is just a small and simple test plugin that doesn't require too much code.
     
  16. Cool... alot of people say "oh im working on a 2000 line plugin I cant show all of the code" and then I relize that they dont kniw how to seperate events and commands..... is this thread solved or are you still stuck on something? If it is a new problem, please start a new thread
     
  17. Actually I'm currently stuck. So far I have made my way through the timer successfully with the player, but then when it tries to cancel the task, for an odd reason the stack traces complains that the timer was not scheduled yet.

    Cooldown class:
    http://hastebin.com/uxuroxumaz.avrasm

    Timer class:
    http://hastebin.com/noxaxijaru.avrasm

    Stacktrace (shows when the task tries to cancel itself):
    http://hastebin.com/ufuxavehip.avrasm

    EDIT: I just added a try and catch into the task, which catches a NullPointerException in case the player went offline during the cooldown, which then cancels the task (of course, like I said when I try to cancel the task, it gives a stack trace saying the task wasn't scheduled yet, so it doesn't cancel the tack and I get the stack trace error every second because the task continuously tries to cancel itself).
     
    #17 HexLazer205, Jul 7, 2015
    Last edited: Jul 7, 2015
  18. Well from what I can see its looking at line 39 of the timer class... but you clearly havent given me the full timer class because line 39 is p.sendMessage, anyway might want to ask someone else about this or create a new thread becausr I dont want to be heading into giving answers about an area I have little experience in
     
  19. You're using BukkitRunnables in the wrong way. When using BukkitRunnables you should schedule tasks using the runTask... methods of the BukkitRunnable itself. You do not need a reference to the Bukkit scheduler.
     
  20. Whoops, that was my problem Rocoty. No wonder it didn't work :p

    Anyway, now I'm getting another error, and here's how it happens: First, I shoot the wither skull fine, then I have the cooldown fine, then I have the "this.cancel()" fine as well, which cancels the task. Then, after that, it wants to give me an error if I try to shoot another wither skull, saying that task 38 is already running. I cancel the task, but for some reason it says it's still running.

    Cooldown:
    http://hastebin.com/igixugulih.avrasm

    Timer:
    http://hastebin.com/uqozinimow.avrasm

    Stacktrace:
    http://hastebin.com/juzufahelu.avrasm
     
Thread Status:
Not open for further replies.