    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.item.Item;
    008    import net.minecraft.nbt.NBTTagCompound;
    009    import net.minecraft.nbt.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.getItemId(), id.getItemType(), id.getModId(), 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.getItemId();
    072                };
    073            };
    074
    075            Map<Integer,ItemData> worldMap = Maps.uniqueIndex(worldSaveItems,idMapFunction);
    076            difference = Maps.difference(worldMap, idMap);
    077            FMLLog.fine("The difference set is %s", difference);
    078            if (!difference.entriesDiffering().isEmpty() || !difference.entriesOnlyOnLeft().isEmpty())
    079            {
    080                FMLLog.severe("FML has detected item discrepancies");
    081                FMLLog.severe("Missing items : %s", difference.entriesOnlyOnLeft());
    082                FMLLog.severe("Mismatched items : %s", difference.entriesDiffering());
    083                isSaveValid = false;
    084                serverValidationLatch.countDown();
    085            }
    086            else
    087            {
    088                isSaveValid = true;
    089                serverValidationLatch.countDown();
    090            }
    091            try
    092            {
    093                clientValidationLatch.await();
    094                if (!shouldContinue)
    095                {
    096                    throw new RuntimeException("This server instance is going to stop abnormally because of a fatal ID mismatch");
    097                }
    098            }
    099            catch (InterruptedException e)
    100            {
    101            }
    102        }
    103
    104        public static void writeItemData(NBTTagList itemList)
    105        {
    106            for (ItemData dat : idMap.values())
    107            {
    108                itemList.appendTag(dat.toNBT());
    109            }
    110        }
    111
    112        /**
    113         * Initialize the server gate
    114         * @param gateCount the countdown amount. If it's 2 we're on the client and the client and server
    115         * will wait at the latch. 1 is a server and the server will proceed
    116         */
    117        public static void initializeServerGate(int gateCount)
    118        {
    119            serverValidationLatch = new CountDownLatch(gateCount - 1);
    120            clientValidationLatch = new CountDownLatch(gateCount - 1);
    121        }
    122
    123        public static MapDifference<Integer, ItemData> gateWorldLoadingForValidation()
    124        {
    125            try
    126            {
    127                serverValidationLatch.await();
    128                if (!isSaveValid)
    129                {
    130                    return difference;
    131                }
    132            }
    133            catch (InterruptedException e)
    134            {
    135            }
    136            difference = null;
    137            return null;
    138        }
    139
    140
    141        public static void releaseGate(boolean carryOn)
    142        {
    143            shouldContinue = carryOn;
    144            clientValidationLatch.countDown();
    145        }
    146
    147        public static Set<ItemData> buildWorldItemData(NBTTagList modList)
    148        {
    149            Set<ItemData> worldSaveItems = Sets.newHashSet();
    150            for (int i = 0; i < modList.tagCount(); i++)
    151            {
    152                NBTTagCompound mod = (NBTTagCompound) modList.tagAt(i);
    153                ItemData dat = new ItemData(mod);
    154                worldSaveItems.add(dat);
    155            }
    156            return worldSaveItems;
    157        }
    158
    159        static void setName(Item item, String name, String modId)
    160        {
    161            int id = item.shiftedIndex;
    162            ItemData itemData = idMap.get(id);
    163            itemData.setName(name,modId);
    164        }
    165
    166
    167
    168    }