    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    }