package net.sourceforge.pain;
import net.sourceforge.pain.data.*;
import net.sourceforge.pain.util.*;
public final class Time implements Runnable {
public static final int PULSE_PER_SCD = 10;
public static final int PULSE_PER_MIN = PULSE_PER_SCD * 60;
private final Object monitor = new Object();
private final int msec_in_pulse = 1000 / PULSE_PER_SCD;
private final Listeners active = new Listeners();
private final Listeners toRemove = new Listeners();
private boolean started = false;
private WorldTime worldTime = null;
private int time = 0;
protected Time() {
}
public void addListener(TimeListener l) {
Log.debug("adding listener:" + l);
active.add(l);
}
public void removeListener(TimeListener l) {
Log.debug("adding to remove listener:" + l);
toRemove.add(l);
}
public void run() {
worldTime = Core.getWorld().getWorldTime();
time = worldTime.getTime();
Log.debug("World Time Start:" + time);
started = true;
long nextPulseTime = System.currentTimeMillis() + msec_in_pulse;
long timeToWait;
while (started) {
try {
timeToWait = nextPulseTime - System.currentTimeMillis();
if (timeToWait > 10) {
synchronized (monitor) {
monitor.wait(timeToWait);
}
}
nextPulseTime = System.currentTimeMillis() + msec_in_pulse;
if (toRemove.size > 0) {
processRemoved();
}
time++;
worldTime.setTime(time);
final TimeListener[] data = active.data;
final int size = active.size;
for (int i = 0; i < size; i++) {
try {
data[i].pulse(time);
} catch (Exception e) {
Log.error(e);
}
}
} catch (Exception e) {
Log.error(e);
} catch (Error e) {
Log.error("CRITICAL BUG! ERROR THROWN!", e);
// new Thread(this).start();
break;
}
}
Core.timeStopped();
}
private synchronized void processRemoved() {
for (int i = 0; i < toRemove.size; i++) {
active.remove(toRemove.data[i]);
}
toRemove.clear();
}
public int getTime() {
return time;
}
public void stopTimer() {
started = false;
}
static final class Listeners {
TimeListener[] data = new TimeListener[10];
int size = 0;
synchronized void add(TimeListener l) {
if (size == data.length) {
TimeListener[] newData = new TimeListener[size * 2];
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
data[size] = l;
size++;
}
synchronized void remove(TimeListener l) {
for (int i = 0; i < size; i++) {
if (data[i] == l) {
int numMoved = size - i - 1;
if (numMoved > 0) {
System.arraycopy(data, i + 1, data, i, numMoved);
}
data[size] = null;
size--;
}
}
}
synchronized void clear() {
for (int i = 0; i < size; i++) {
data[i] = null;
}
size = 0;
}
}
}