mirror of
https://github.com/2006-Scape/2006Scape.git
synced 2026-07-08 00:32:12 +00:00
init, thx MrExtremez
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
package redone.event;
|
||||
|
||||
/**
|
||||
* What the event must implement
|
||||
*
|
||||
* @author Stuart <RogueX>
|
||||
*/
|
||||
public abstract class CycleEvent {
|
||||
|
||||
/**
|
||||
* Code which should be ran when the event is executed
|
||||
*
|
||||
* @param container
|
||||
*/
|
||||
public abstract void execute(CycleEventContainer container);
|
||||
|
||||
/**
|
||||
* Code which should be ran when the event stops
|
||||
*/
|
||||
public abstract void stop();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package redone.event;
|
||||
|
||||
/**
|
||||
* The wrapper for our event
|
||||
*
|
||||
* @author Stuart <RogueX>
|
||||
* @author Null++
|
||||
*/
|
||||
|
||||
public class CycleEventContainer {
|
||||
|
||||
/**
|
||||
* Event owner
|
||||
*/
|
||||
private final Object owner;
|
||||
|
||||
/**
|
||||
* Is the event running or not
|
||||
*/
|
||||
private boolean isRunning;
|
||||
|
||||
/**
|
||||
* The amount of cycles per event execution
|
||||
*/
|
||||
private int tick;
|
||||
|
||||
/**
|
||||
* The actual event
|
||||
*/
|
||||
private final CycleEvent event;
|
||||
|
||||
/**
|
||||
* The current amount of cycles passed
|
||||
*/
|
||||
private int cyclesPassed;
|
||||
|
||||
/**
|
||||
* The event ID
|
||||
*/
|
||||
private final int eventID;
|
||||
|
||||
/**
|
||||
* Sets the event containers details
|
||||
*
|
||||
* @param owner
|
||||
* , the owner of the event
|
||||
* @param event
|
||||
* , the actual event to run
|
||||
* @param tick
|
||||
* , the cycles between execution of the event
|
||||
*/
|
||||
public CycleEventContainer(int id, Object owner, CycleEvent event, int tick) {
|
||||
eventID = id;
|
||||
this.owner = owner;
|
||||
this.event = event;
|
||||
isRunning = true;
|
||||
cyclesPassed = 0;
|
||||
this.tick = tick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the contents of the event
|
||||
*/
|
||||
public void execute() {
|
||||
event.execute(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the event from running
|
||||
*/
|
||||
public void stop() {
|
||||
isRunning = false;
|
||||
event.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the event need to be ran?
|
||||
*
|
||||
* @return true yes false no
|
||||
*/
|
||||
public boolean needsExecution() {
|
||||
if (!isRunning()) {
|
||||
return false;
|
||||
}
|
||||
if (++cyclesPassed >= tick) {
|
||||
cyclesPassed = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner of the event
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Object getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the event running?
|
||||
*
|
||||
* @return true yes false no
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event id
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public int getID() {
|
||||
return eventID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current cycle/tick.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getTick() {
|
||||
return tick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of cycles between the execution
|
||||
*
|
||||
* @param tick
|
||||
*/
|
||||
public void setTick(int tick) {
|
||||
this.tick = tick;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package redone.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Handles all of our cycle based events
|
||||
*
|
||||
* @author Stuart <RogueX>
|
||||
* @author Null++
|
||||
*/
|
||||
public class CycleEventHandler {
|
||||
|
||||
/**
|
||||
* The instance of this class
|
||||
*/
|
||||
private static CycleEventHandler instance;
|
||||
|
||||
/**
|
||||
* Returns the instance of this class
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static CycleEventHandler getSingleton() {
|
||||
if (instance == null) {
|
||||
instance = new CycleEventHandler();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds all of our events currently being ran
|
||||
*/
|
||||
private final List<CycleEventContainer> events;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class
|
||||
*/
|
||||
public CycleEventHandler() {
|
||||
events = new ArrayList<CycleEventContainer>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event to the list
|
||||
*
|
||||
* @param id
|
||||
* @param owner
|
||||
* @param event
|
||||
* @param cycles
|
||||
*/
|
||||
public void addEvent(int id, Object owner, CycleEvent event, int cycles) {
|
||||
events.add(new CycleEventContainer(id, owner, event, cycles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event to the list
|
||||
*
|
||||
* @param owner
|
||||
* @param event
|
||||
* @param cycles
|
||||
*/
|
||||
public void addEvent(Object owner, CycleEvent event, int cycles) {
|
||||
events.add(new CycleEventContainer(-1, owner, event, cycles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute and remove events
|
||||
*/
|
||||
public void process() {
|
||||
List<CycleEventContainer> eventsCopy = new ArrayList<CycleEventContainer>(
|
||||
events);
|
||||
List<CycleEventContainer> remove = new ArrayList<CycleEventContainer>();
|
||||
for (CycleEventContainer c : eventsCopy) {
|
||||
if (c != null) {
|
||||
if (c.needsExecution() && c.isRunning()) {
|
||||
c.execute();
|
||||
if (!c.isRunning()) {
|
||||
remove.add(c);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (CycleEventContainer c : remove) {
|
||||
events.remove(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of events currently running
|
||||
*
|
||||
* @return amount
|
||||
*/
|
||||
public int getEventsCount() {
|
||||
return events.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops all events for a specific owner and id
|
||||
*
|
||||
* @param owner
|
||||
*/
|
||||
public void stopEvents(Object owner) {
|
||||
for (CycleEventContainer c : events) {
|
||||
if (c.getOwner() == owner) {
|
||||
c.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops all events for a specific owner and id
|
||||
*
|
||||
* @param owner
|
||||
* @param id
|
||||
*/
|
||||
public void stopEvents(Object owner, int id) {
|
||||
for (CycleEventContainer c : events) {
|
||||
if (c.getOwner() == owner && id == c.getID()) {
|
||||
c.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops all events for a specific owner and id
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void stopEvents(int id) {
|
||||
for (CycleEventContainer c : events) {
|
||||
if (id == c.getID()) {
|
||||
c.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package redone.event;
|
||||
|
||||
/**
|
||||
* Represents a periodic task that can be scheduled with a {@link TaskScheduler}
|
||||
* .
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public abstract class Task {
|
||||
|
||||
/**
|
||||
* The number of cycles between consecutive executions of this task.
|
||||
*/
|
||||
private final int delay;
|
||||
|
||||
/**
|
||||
* A flag which indicates if this task should be executed once immediately.
|
||||
*/
|
||||
private final boolean immediate;
|
||||
|
||||
/**
|
||||
* The current 'count down' value. When this reaches zero the task will be
|
||||
* executed.
|
||||
*/
|
||||
private int countdown;
|
||||
|
||||
/**
|
||||
* A flag which indicates if this task is still running.
|
||||
*/
|
||||
private boolean running = true;
|
||||
|
||||
/**
|
||||
* Creates a new task with a delay of 1 cycle.
|
||||
*/
|
||||
public Task() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new task with a delay of 1 cycle and immediate flag.
|
||||
*
|
||||
* @param immediate
|
||||
* A flag that indicates if for the first execution there should
|
||||
* be no delay.
|
||||
*/
|
||||
public Task(boolean immediate) {
|
||||
this(1, immediate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new task with the specified delay.
|
||||
*
|
||||
* @param delay
|
||||
* The number of cycles between consecutive executions of this
|
||||
* task.
|
||||
* @throws IllegalArgumentException
|
||||
* if the {@code delay} is not positive.
|
||||
*/
|
||||
public Task(int delay) {
|
||||
this(delay, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new task with the specified delay and immediate flag.
|
||||
*
|
||||
* @param delay
|
||||
* The number of cycles between consecutive executions of this
|
||||
* task.
|
||||
* @param immediate
|
||||
* A flag which indicates if for the first execution there should
|
||||
* be no delay.
|
||||
* @throws IllegalArgumentException
|
||||
* if the {@code delay} is not positive.
|
||||
*/
|
||||
public Task(int delay, boolean immediate) {
|
||||
checkDelay(delay);
|
||||
this.delay = delay;
|
||||
countdown = delay;
|
||||
this.immediate = immediate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this task is an immediate task.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isImmediate() {
|
||||
return immediate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the task is running.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the task is stopped.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isStopped() {
|
||||
return !running;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be called by the scheduling class every cycle. It
|
||||
* updates the {@link #countdown} and calls the {@link #execute()} method if
|
||||
* necessary.
|
||||
*
|
||||
* @return A flag indicating if the task is running.
|
||||
*/
|
||||
public boolean tick() {
|
||||
if (running && --countdown == 0) {
|
||||
execute();
|
||||
countdown = delay;
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs this task's action.
|
||||
*/
|
||||
protected abstract void execute();
|
||||
|
||||
/**
|
||||
* Changes the delay of this task.
|
||||
*
|
||||
* @param delay
|
||||
* The number of cycles between consecutive executions of this
|
||||
* task.
|
||||
* @throws IllegalArgumentException
|
||||
* if the {@code delay} is not positive.
|
||||
*/
|
||||
public void setDelay(int delay) {
|
||||
checkDelay(delay);
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this task.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* if the task has already been stopped.
|
||||
*/
|
||||
public void stop() {
|
||||
checkStopped();
|
||||
running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the delay is negative and throws an exception if so.
|
||||
*
|
||||
* @param delay
|
||||
* The delay.
|
||||
* @throws IllegalArgumentException
|
||||
* if the delay is not positive.
|
||||
*/
|
||||
private void checkDelay(int delay) {
|
||||
if (delay <= 0) {
|
||||
throw new IllegalArgumentException("Delay must be positive.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this task has been stopped and throws an exception if so.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* if the task has been stopped.
|
||||
*/
|
||||
private void checkStopped() {
|
||||
if (!running) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package redone.event;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A class which schedules the execution of {@link Task}s.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class TaskScheduler implements Runnable {
|
||||
|
||||
/**
|
||||
* A logger used to report error messages.
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(TaskScheduler.class
|
||||
.getName());
|
||||
|
||||
/**
|
||||
* The time period, in milliseconds, of a single cycle.
|
||||
*/
|
||||
private static final int TIME_PERIOD = 600;
|
||||
|
||||
/**
|
||||
* The {@link ScheduledExecutorService} which schedules calls to the
|
||||
* {@link #run()} method.
|
||||
*/
|
||||
private final ScheduledExecutorService service = Executors
|
||||
.newSingleThreadScheduledExecutor();
|
||||
|
||||
/**
|
||||
* A list of active tasks.
|
||||
*/
|
||||
private final List<Task> tasks = new ArrayList<Task>();
|
||||
|
||||
/**
|
||||
* A queue of tasks that still need to be added.
|
||||
*/
|
||||
private final Queue<Task> newTasks = new ArrayDeque<Task>();
|
||||
|
||||
/**
|
||||
* Creates and starts the task scheduler.
|
||||
*/
|
||||
public TaskScheduler() {
|
||||
service.scheduleAtFixedRate(this, 0, TIME_PERIOD, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the task scheduler.
|
||||
*/
|
||||
public void terminate() {
|
||||
service.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the specified task. If this scheduler has been stopped with the
|
||||
* {@link #terminate()} method the task will not be executed or
|
||||
* garbage-collected.
|
||||
*
|
||||
* @param task
|
||||
* The task to schedule.
|
||||
*/
|
||||
public void schedule(final Task task) {
|
||||
if (task.isImmediate()) {
|
||||
service.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
task.execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
synchronized (newTasks) {
|
||||
newTasks.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is automatically called every cycle by the
|
||||
* {@link ScheduledExecutorService} and executes, adds and removes
|
||||
* {@link Task}s. It should not be called directly as this will lead to
|
||||
* concurrency issues and inaccurate time-keeping.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (newTasks) {
|
||||
Task task;
|
||||
while ((task = newTasks.poll()) != null) {
|
||||
tasks.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator<Task> it = tasks.iterator(); it.hasNext();) {
|
||||
Task task = it.next();
|
||||
try {
|
||||
if (!task.tick()) {
|
||||
it.remove();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.SEVERE, "Exception during task execution.", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user