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 }