package com.comphenix.xp;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.ObjectUtils;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import com.comphenix.xp.listeners.PlayerCleanupListener;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
/**
* Schedules actions for different players.
*
* @author Kristian
*/
public class PlayerScheduler implements PlayerCleanupListener {
private SetMultimap<String, PlayerRunnable> tasks = Multimaps.synchronizedSetMultimap(createMap());
private int defaultTicks;
private BukkitScheduler scheduler;
private Plugin plugin;
public PlayerScheduler(BukkitScheduler scheduler, Plugin plugin) {
this.scheduler = scheduler;
this.plugin = plugin;
}
// Creates our multimap
private static SetMultimap<String, PlayerRunnable> createMap() {
return HashMultimap.create();
}
/**
* Schedules a task for execution on the main thread, associated with the given player.
* @param player - player to execute on behalf of.
* @param tag - unique tag or task name.
*/
public void scheduleSync(Player player, String tag, Runnable runnable) {
if (runnable == null)
throw new NullArgumentException("runnable");
if (player == null)
throw new NullArgumentException("player");
if (tag == null)
throw new NullArgumentException("tag");
PlayerRunnable playerTask = new PlayerRunnable(player.getName(), tag, runnable);
Integer taskID = scheduler.scheduleSyncDelayedTask(plugin, playerTask, defaultTicks);
// Now, update the task ID
playerTask.setTaskID(taskID);
tasks.put(player.getName(), playerTask);
}
private Set<PlayerRunnable> getTasks(Player player) {
return tasks.get(player.getName());
}
public Set<PlayerRunnable> getTasks(Player player, String tag) {
Set<PlayerRunnable> copy = new HashSet<PlayerRunnable>();
// Filter out runnables with different tags
for (PlayerRunnable runnable : getTasks(player)) {
if (ObjectUtils.equals(runnable.getTag(), tag)) {
copy.add(runnable);
}
}
return copy;
}
@Override
public void removePlayerCache(Player player) {
// Stop all associated tasks
for (PlayerRunnable runnable : getTasks(player)) {
scheduler.cancelTask(runnable.getTaskID());
}
// Then remove them
tasks.removeAll(player.getName());
}
public BukkitScheduler getScheduler() {
return scheduler;
}
public Plugin getPlugin() {
return plugin;
}
/**
* Retrieves the current default number of ticks (50 ms per tick) until a task is executed.
* @return Number of ticks until a task is executed.
*/
public int getDefaultTicks() {
return defaultTicks;
}
/**
* Sets the current default number of server ticks (50 ms per tick) until a task is executed.
* @param defaultTicks
*/
public void setDefaultTicks(int defaultTicks) {
this.defaultTicks = defaultTicks;
}
// Our runnable that cleans up after itself
public class PlayerRunnable implements Runnable {
// Name and task ID
private String name;
private String tag;
private int taskID;
// The task to execute
private Runnable task;
public PlayerRunnable(String name, String tag, Runnable task) {
this.name = name;
this.tag = tag;
this.task = task;
}
@Override
public void run() {
task.run();
// Clean up after ourself
tasks.remove(name, this);
}
public String getName() {
return name;
}
public Runnable getTask() {
return task;
}
public String getTag() {
return tag;
}
public int getTaskID() {
return taskID;
}
public void setTaskID(int taskID) {
this.taskID = taskID;
}
}
}