    001package cpw.mods.fml.common.registry;
    002
    003import java.util.List;
    004import java.util.PriorityQueue;
    005import java.util.concurrent.atomic.AtomicLong;
    006
    007import com.google.common.collect.Queues;
    008
    009import cpw.mods.fml.common.IScheduledTickHandler;
    010import cpw.mods.fml.common.ITickHandler;
    011import cpw.mods.fml.common.SingleIntervalHandler;
    012import cpw.mods.fml.relauncher.Side;
    013
    014public class TickRegistry
    015{
    016
    017    /**
    018     * We register our delegate here
    019     * @param handler
    020     */
    021
    022    public static class TickQueueElement implements Comparable<TickQueueElement>
    023    {
    024        public TickQueueElement(IScheduledTickHandler ticker, long tickCounter)
    025        {
    026            this.ticker = ticker;
    027            update(tickCounter);
    028        }
    029        @Override
    030        public int compareTo(TickQueueElement o)
    031        {
    032            return (int)(next - o.next);
    033        }
    034
    035        public void update(long tickCounter)
    036        {
    037            next = tickCounter + Math.max(ticker.nextTickSpacing(),1);
    038        }
    039
    040        private long next;
    041        public IScheduledTickHandler ticker;
    042
    043        public boolean scheduledNow(long tickCounter)
    044        {
    045            return tickCounter >= next;
    046        }
    047    }
    048
    049    private static PriorityQueue<TickQueueElement> clientTickHandlers = Queues.newPriorityQueue();
    050    private static PriorityQueue<TickQueueElement> serverTickHandlers = Queues.newPriorityQueue();
    051
    052    private static AtomicLong clientTickCounter = new AtomicLong();
    053    private static AtomicLong serverTickCounter = new AtomicLong();
    054
    055    public static void registerScheduledTickHandler(IScheduledTickHandler handler, Side side)
    056    {
    057        getQueue(side).add(new TickQueueElement(handler, getCounter(side).get()));
    058    }
    059
    060    /**
    061     * @param side the side to get the tick queue for
    062     * @return the queue for the effective side
    063     */
    064    private static PriorityQueue<TickQueueElement> getQueue(Side side)
    065    {
    066        return side.isClient() ? clientTickHandlers : serverTickHandlers;
    067    }
    068
    069    private static AtomicLong getCounter(Side side)
    070    {
    071        return side.isClient() ? clientTickCounter : serverTickCounter;
    072    }
    073    public static void registerTickHandler(ITickHandler handler, Side side)
    074    {
    075        registerScheduledTickHandler(new SingleIntervalHandler(handler), side);
    076    }
    077
    078    public static void updateTickQueue(List<IScheduledTickHandler> ticks, Side side)
    079    {
    080        synchronized (ticks)
    081        {
    082            ticks.clear();
    083            long tick = getCounter(side).incrementAndGet();
    084            PriorityQueue<TickQueueElement> tickHandlers = getQueue(side);
    085
    086            while (true)
    087            {
    088                if (tickHandlers.size()==0 || !tickHandlers.peek().scheduledNow(tick))
    089                {
    090                    break;
    091                }
    092                TickRegistry.TickQueueElement tickQueueElement  = tickHandlers.poll();
    093                tickQueueElement.update(tick);
    094                tickHandlers.offer(tickQueueElement);
    095                ticks.add(tickQueueElement.ticker);
    096            }
    097        }
    098    }
    099
    100}