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
062     * @return
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}