001    package cpw.mods.fml.common.registry;
002    
003    import java.util.List;
004    import java.util.PriorityQueue;
005    import java.util.concurrent.atomic.AtomicLong;
006    
007    import com.google.common.collect.Queues;
008    
009    import cpw.mods.fml.common.IScheduledTickHandler;
010    import cpw.mods.fml.common.ITickHandler;
011    import cpw.mods.fml.common.SingleIntervalHandler;
012    import cpw.mods.fml.relauncher.Side;
013    
014    public 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    }