Skip to content

Instantly share code, notes, and snippets.

@Garris0n-
Last active August 1, 2022 17:24
Show Gist options
  • Save Garris0n-/d0ac9228387b95d0f486 to your computer and use it in GitHub Desktop.
Save Garris0n-/d0ac9228387b95d0f486 to your computer and use it in GitHub Desktop.
Lazy cooldown example
//DISCLAIMER: NOT YET TESTED, THIS CODE MAY CONTAIN SYNTAX ERRORS
//this demonstrates lazy cooldowns, because using a list and a scheduler is an absolutely terrible idea
//BCBroz, why do you cause us so much pain...*sigh*
//in this example, the ability is to be able to break a block instantly with your fist once per minute
//as this is an example for tutorial purposes, a lot of code is dragged out into variables for clarity
//please do not copy-paste or use this code without reading the comments and fully understanding what is going on
private HashMap<UUID, Long> map = new HashMap<UUID, Long>(); //the map to hold our cooldown times
private static final int COOLDOWN_TIME_IN_SECONDS = 60; //our cooldown time, in seconds for readability
@EventHandler //event handler
public void onClick(PlayerInteractEvent event){ //an example event
Player player = event.getPlayer(); //get the player involved
if(!event.getAction().equals(Action.LEFT_CLICK_BLOCK) || !player.getItemInHand() != null)
return; //for this example, they must punch a block with their fist
if(onCooldown(player)){ //if they're still on cooldown, they can't use it, so we handle that
long timeLeftInSeconds = getTimeLeft(player, TimeUnit.SECONDS); //get the time left in seconds from our fancy method
player.sendMessage(ChatColor.RED + "You are on cooldown for another " + timeLeftInSeconds + " seconds."); //tell the player about the cooldown
event.setCancelled(true); //cancel the punch, just because it's part of the example
return; //exit the method so we don't continue processing the event
}
event.getClickedBlock().breakNaturally(); //for this example, the player instantly breaks a block
player.playSound(event.getClickedBlock().getLocation(), Sound.EXPLODE, 1f, 1f); //for this example, we also play an explode sound
logUse(player); //log the use of the ability
}
@EventHandler //event handler
public void onQuit(PlayerQuitEvent event){ //on quit, we clean up
cleanup(event.getPlayer()); //cleanup - read the method
}
private boolean onCooldown(Player player){ //a method to check if they're still on cooldown
long timeElapsed = getTimeElapsedInMillis(player); //get the amount of time elapsed since they last used the ability (an milliseconds)
if(timeElapsed == -1) //the method returns -1 if they're not in the map
return false; //they're not even in the map, so they're not on cooldown
long cooldownTimeInMillis = getCooldownTimeInMillis(); //get the cooldown time in milliseconds, that's what we're using
return timeElapsed <= cooldownTimeInMillis; //if the time elapsed is less than or equal to the time of the cooldown, they're not allowed to use it yet
}
private void logUse(Player player){ //a method to log the time they use the ability
map.put(player.getUniqueId(), System.currentTimeMillis()); //put the player's UUID and the current time (in milliseconds) into the map
}
private void cleanup(Player player){
//remove the player from the map, just so we don't have lingering cooldowns for no reason
//note that this may not be the desired behavior since the player could abuse it to break more blocks faster
//by logging out and in constantly
map.remove(player.getUniqueId());
}
private long getTimeLeft(Player player, TimeUnit timeUnit){ //gets the time left for the player in a certain unit, intended for display purposes
if(!onCooldown(player)) //bit of a sanity check, but whatever, this is an example
return -1; //they're not even on cooldown, we can't get the time left, so we'll just return -1
long timeElapsed = getTimeElapsedInMillis(player) //get the time elapsed in milliseconds
long cooldownTime = getCooldownTimeInMillis(); //get the cooldown time in milliseconds
long timeUntilUse = cooldownTime - timeElapsed; //get the time until they can use the ability again
return TimeUnit.MILLISECONDS.convert(timeUnit, timeUntilUse); //convert the time to the requested unit and return it
}
private long getTimeElapsedInMillis(Player player){ //gets the time elapsed since the last use of the ability in milliseconds
if(!map.containsKey(player.getUniqueId())
return -1; //they're not in the map anyway, just return -1
long currentTime = System.currentTimeMillis(); //get the current time in milliseconds
long lastUsed = map.get(player.getUniqueId()); //get the time (in milliseconds) that they last used the ability
long timeElapsed = currentTime - lastUsed; //get the amount of time elapsed since they last used the ability (again, in milliseconds)
return timeElapsed; //return the time elapsed
}
private long getCooldownTimeInMillis(){ //get the cooldown length in milliseconds
return TimeUnit.SECONDS.toMillis(COOLDOWN_TIME_IN_SECONDS); //convert the cooldown time to milliseconds and return it
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment