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 }