Skip to content

Instantly share code, notes, and snippets.

@dumptruckman
Created July 25, 2012 04:18
Show Gist options
  • Save dumptruckman/3174361 to your computer and use it in GitHub Desktop.
Save dumptruckman/3174361 to your computer and use it in GitHub Desktop.
A class for a Bukkit countdown task complete with warnings and "events" for doing stuff when started/finished
public abstract class CountdownTask implements Runnable {
private boolean started = false;
private boolean dead = false;
private int countdown;
private long lastTime = 0L;
private final Set<Integer> warnings = new HashSet<Integer>();
private final Plugin plugin;
public CountdownTask(final Plugin plugin, final int countdown) {
this.plugin = plugin;
this.countdown = countdown;
warnings = new HashSet<Integer>();
}
protected final void setCountdown(int countdown) {
this.countdown = countdown;
}
/**
* Adds warning times to the countdown.
* The collection should contain the seconds at which a warning should occur.
* When a warning time is reached countdownWarning() is called.
*/
public final void setWarnings(Collection<Integer> warnings) {
this.warnings.addAll(warnings);
}
/**
* Starts the countdown
*/
public final void start() {
if (!started && !dead) {
lastTime = System.currentTimeMillis();
started = true;
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), this, 5L);
}
}
/**
* Call to abruptly end the countdown and do nothing further.
*/
public final void kill() {
dead = true;
}
@Override
public final void run() {
if (started) {
final long timeDiff = System.currentTimeMillis() - lastTime;
if (timeDiff < 1000) {
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), this, 5L);
return;
} else {
// Play catch-up if needed
final long missed = timeDiff / 1000;
for (int i = 1; i < missed; i++) {
if (dead) {
break;
}
processCountdown();
}
lastTime += missed * 1000L;
}
if (!dead && countdown > 0 && !shouldEnd()) {
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), this, 5L);
}
processCountdown();
}
}
private void processCountdown() {
if (shouldCountdown() && !dead) {
countdown--;
if (countdown <= 0) {
dead = true;
countdownFinished();
} else if (warnings.contains(countdown)) {
countdownWarning(countdown);
}
}
}
/**
* Implement to do something at the start of the countdown.
*/
public abstract void onStart();
/**
* Implement for a way to end the countdown early.
*
* @return true to end countdown, false for countdown to continue
*/
public abstract boolean shouldEnd();
/**
* Implement for a way to effectively pause the countdown.
* When this returns false the countdown will halt.
* MUST return true to countdown at all.
*
* @return true to countdown, false to NOT countdown
*/
public abstract boolean shouldCountdown();
/**
* Implement if you are using countdown warnings as defined via the setWarnings() method.
* This is called when the countdown reaches the warning times.
*
* @param warning The warning time the countdown has reached.
*/
public abstract void countdownWarning(int warning);
/**
* Implement to do something when the countdown has completed (reached 0).
*/
public abstract void countdownFinished();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment