001    package cpw.mods.fml.common.registry;
002    
003    import java.util.Map;
004    import java.util.Set;
005    import java.util.concurrent.CountDownLatch;
006    
007    import net.minecraft.src.Item;
008    import net.minecraft.src.NBTTagCompound;
009    import net.minecraft.src.NBTTagList;
010    
011    import com.google.common.base.Function;
012    import com.google.common.collect.MapDifference;
013    import com.google.common.collect.Maps;
014    import com.google.common.collect.Sets;
015    
016    import cpw.mods.fml.common.FMLLog;
017    import cpw.mods.fml.common.Loader;
018    import cpw.mods.fml.common.LoaderState;
019    import cpw.mods.fml.common.ModContainer;
020    
021    public class GameData {
022        private static Map<Integer, ItemData> idMap = Maps.newHashMap();
023        private static CountDownLatch serverValidationLatch;
024        private static CountDownLatch clientValidationLatch;
025        private static MapDifference<Integer, ItemData> difference;
026        private static boolean shouldContinue = true;
027        private static boolean isSaveValid = true;
028    
029        public static void newItemAdded(Item item)
030        {
031            ModContainer mc = Loader.instance().activeModContainer();
032            if (mc == null)
033            {
034                mc = Loader.instance().getMinecraftModContainer();
035                if (Loader.instance().hasReachedState(LoaderState.AVAILABLE))
036                {
037                    FMLLog.severe("It appears something has tried to allocate an Item outside of the initialization phase of Minecraft, this could be very bad for your network connectivity.");
038                }
039            }
040            String itemType = item.getClass().getName();
041            ItemData itemData = new ItemData(item, mc);
042            if (idMap.containsKey(item.shiftedIndex))
043            {
044                ItemData id = idMap.get(item.shiftedIndex);
045                FMLLog.warning("[ItemTracker] The mod %s is attempting to overwrite existing item at %d (%s from %s) with %s", mc.getModId(), id.itemId, id.itemType, id.modId, itemType);
046            }
047            idMap.put(item.shiftedIndex, itemData);
048            FMLLog.fine("[ItemTracker] Adding item %s(%d) owned by %s", item.getClass().getName(), item.shiftedIndex, mc.getModId());
049        }
050    
051        public static void validateWorldSave(Set<ItemData> worldSaveItems)
052        {
053            isSaveValid = true;
054            shouldContinue = true;
055            // allow ourselves to continue if there's no saved data
056            if (worldSaveItems == null)
057            {
058                serverValidationLatch.countDown();
059                try
060                {
061                    clientValidationLatch.await();
062                }
063                catch (InterruptedException e)
064                {
065                }
066                return;
067            }
068    
069            Function<? super ItemData, Integer> idMapFunction = new Function<ItemData, Integer>() {
070                public Integer apply(ItemData input) {
071                    return input.itemId;
072                };
073            };
074    
075            Map<Integer,ItemData> worldMap = Maps.uniqueIndex(worldSaveItems,idMapFunction);
076            difference = Maps.difference(worldMap, idMap);
077            if (!difference.entriesDiffering().isEmpty() || !difference.entriesOnlyOnLeft().isEmpty())
078            {
079                isSaveValid = false;
080                serverValidationLatch.countDown();
081            }
082            else
083            {
084                isSaveValid = true;
085                serverValidationLatch.countDown();
086            }
087            try
088            {
089                clientValidationLatch.await();
090                if (!shouldContinue)
091                {
092                    throw new RuntimeException("This server instance is going to stop abnormally because of a fatal ID mismatch");
093                }
094            }
095            catch (InterruptedException e)
096            {
097            }
098        }
099    
100        public static void writeItemData(NBTTagList itemList)
101        {
102            for (ItemData dat : idMap.values())
103            {
104                itemList.appendTag(dat.toNBT());
105            }
106        }
107    
108        /**
109         * Initialize the server gate
110         * @param gateCount the countdown amount. If it's 2 we're on the client and the client and server
111         * will wait at the latch. 1 is a server and the server will proceed
112         */
113        public static void initializeServerGate(int gateCount)
114        {
115            serverValidationLatch = new CountDownLatch(gateCount - 1);
116            clientValidationLatch = new CountDownLatch(gateCount - 1);
117        }
118    
119        public static MapDifference<Integer, ItemData> gateWorldLoadingForValidation()
120        {
121            try
122            {
123                serverValidationLatch.await();
124                if (!isSaveValid)
125                {
126                    return difference;
127                }
128            }
129            catch (InterruptedException e)
130            {
131            }
132            difference = null;
133            return null;
134        }
135    
136    
137        public static void releaseGate(boolean carryOn)
138        {
139            shouldContinue = carryOn;
140            clientValidationLatch.countDown();
141        }
142    
143        public static Set<ItemData> buildWorldItemData(NBTTagList modList)
144        {
145            Set<ItemData> worldSaveItems = Sets.newHashSet();
146            for (int i = 0; i < modList.tagCount(); i++)
147            {
148                NBTTagCompound mod = (NBTTagCompound) modList.tagAt(i);
149                ItemData dat = new ItemData(mod);
150                worldSaveItems.add(dat);
151            }
152            return worldSaveItems;
153        }
154    
155    
156    
157    }