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; } } }