001/* 002 * Forge Mod Loader 003 * Copyright (c) 2012-2013 cpw. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser Public License v2.1 006 * which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 008 * 009 * Contributors: 010 * cpw - implementation 011 */ 012 013package cpw.mods.fml.common.registry; 014 015import java.util.List; 016import java.util.PriorityQueue; 017import java.util.concurrent.atomic.AtomicLong; 018 019import com.google.common.collect.Queues; 020 021import cpw.mods.fml.common.IScheduledTickHandler; 022import cpw.mods.fml.common.ITickHandler; 023import cpw.mods.fml.common.SingleIntervalHandler; 024import cpw.mods.fml.relauncher.Side; 025 026public class TickRegistry 027{ 028 029 /** 030 * We register our delegate here 031 * @param handler 032 */ 033 034 public static class TickQueueElement implements Comparable<TickQueueElement> 035 { 036 public TickQueueElement(IScheduledTickHandler ticker, long tickCounter) 037 { 038 this.ticker = ticker; 039 update(tickCounter); 040 } 041 @Override 042 public int compareTo(TickQueueElement o) 043 { 044 return (int)(next - o.next); 045 } 046 047 public void update(long tickCounter) 048 { 049 next = tickCounter + Math.max(ticker.nextTickSpacing(),1); 050 } 051 052 private long next; 053 public IScheduledTickHandler ticker; 054 055 public boolean scheduledNow(long tickCounter) 056 { 057 return tickCounter >= next; 058 } 059 } 060 061 private static PriorityQueue<TickQueueElement> clientTickHandlers = Queues.newPriorityQueue(); 062 private static PriorityQueue<TickQueueElement> serverTickHandlers = Queues.newPriorityQueue(); 063 064 private static AtomicLong clientTickCounter = new AtomicLong(); 065 private static AtomicLong serverTickCounter = new AtomicLong(); 066 067 public static void registerScheduledTickHandler(IScheduledTickHandler handler, Side side) 068 { 069 getQueue(side).add(new TickQueueElement(handler, getCounter(side).get())); 070 } 071 072 /** 073 * @param side the side to get the tick queue for 074 * @return the queue for the effective side 075 */ 076 private static PriorityQueue<TickQueueElement> getQueue(Side side) 077 { 078 return side.isClient() ? clientTickHandlers : serverTickHandlers; 079 } 080 081 private static AtomicLong getCounter(Side side) 082 { 083 return side.isClient() ? clientTickCounter : serverTickCounter; 084 } 085 public static void registerTickHandler(ITickHandler handler, Side side) 086 { 087 registerScheduledTickHandler(new SingleIntervalHandler(handler), side); 088 } 089 090 public static void updateTickQueue(List<IScheduledTickHandler> ticks, Side side) 091 { 092 synchronized (ticks) 093 { 094 ticks.clear(); 095 long tick = getCounter(side).incrementAndGet(); 096 PriorityQueue<TickQueueElement> tickHandlers = getQueue(side); 097 098 while (true) 099 { 100 if (tickHandlers.size()==0 || !tickHandlers.peek().scheduledNow(tick)) 101 { 102 break; 103 } 104 TickRegistry.TickQueueElement tickQueueElement = tickHandlers.poll(); 105 tickQueueElement.update(tick); 106 tickHandlers.offer(tickQueueElement); 107 ticks.add(tickQueueElement.ticker); 108 } 109 } 110 } 111 112}