001    package net.minecraft.stats;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.ArrayList;
006    import java.util.HashMap;
007    import java.util.HashSet;
008    import java.util.Iterator;
009    import java.util.List;
010    import java.util.Map;
011    import net.minecraft.block.Block;
012    import net.minecraft.item.Item;
013    import net.minecraft.item.ItemStack;
014    import net.minecraft.item.crafting.CraftingManager;
015    import net.minecraft.item.crafting.FurnaceRecipes;
016    import net.minecraft.item.crafting.IRecipe;
017    import net.minecraft.util.StatCollector;
018    
019    public class StatList
020    {
021        /** Tracks one-off stats. */
022        protected static Map oneShotStats = new HashMap();
023        public static List allStats = new ArrayList();
024        public static List generalStats = new ArrayList();
025        public static List itemStats = new ArrayList();
026    
027        /** Tracks the number of times a given block or item has been mined. */
028        public static List objectMineStats = new ArrayList();
029    
030        /** times the game has been started */
031        public static StatBase startGameStat = (new StatBasic(1000, "stat.startGame")).initIndependentStat().registerStat();
032    
033        /** times a world has been created */
034        public static StatBase createWorldStat = (new StatBasic(1001, "stat.createWorld")).initIndependentStat().registerStat();
035    
036        /** the number of times you have loaded a world */
037        public static StatBase loadWorldStat = (new StatBasic(1002, "stat.loadWorld")).initIndependentStat().registerStat();
038    
039        /** number of times you've joined a multiplayer world */
040        public static StatBase joinMultiplayerStat = (new StatBasic(1003, "stat.joinMultiplayer")).initIndependentStat().registerStat();
041    
042        /** number of times you've left a game */
043        public static StatBase leaveGameStat = (new StatBasic(1004, "stat.leaveGame")).initIndependentStat().registerStat();
044    
045        /** number of minutes you have played */
046        public static StatBase minutesPlayedStat = (new StatBasic(1100, "stat.playOneMinute", StatBase.timeStatType)).initIndependentStat().registerStat();
047    
048        /** distance you've walked */
049        public static StatBase distanceWalkedStat = (new StatBasic(2000, "stat.walkOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
050    
051        /** distance you have swam */
052        public static StatBase distanceSwumStat = (new StatBasic(2001, "stat.swimOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
053    
054        /** the distance you have fallen */
055        public static StatBase distanceFallenStat = (new StatBasic(2002, "stat.fallOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
056    
057        /** the distance you've climbed */
058        public static StatBase distanceClimbedStat = (new StatBasic(2003, "stat.climbOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
059    
060        /** the distance you've flown */
061        public static StatBase distanceFlownStat = (new StatBasic(2004, "stat.flyOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
062    
063        /** the distance you've dived */
064        public static StatBase distanceDoveStat = (new StatBasic(2005, "stat.diveOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
065    
066        /** the distance you've traveled by minecart */
067        public static StatBase distanceByMinecartStat = (new StatBasic(2006, "stat.minecartOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
068    
069        /** the distance you've traveled by boat */
070        public static StatBase distanceByBoatStat = (new StatBasic(2007, "stat.boatOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
071    
072        /** the distance you've traveled by pig */
073        public static StatBase distanceByPigStat = (new StatBasic(2008, "stat.pigOneCm", StatBase.distanceStatType)).initIndependentStat().registerStat();
074    
075        /** the times you've jumped */
076        public static StatBase jumpStat = (new StatBasic(2010, "stat.jump")).initIndependentStat().registerStat();
077    
078        /** the distance you've dropped (or times you've fallen?) */
079        public static StatBase dropStat = (new StatBasic(2011, "stat.drop")).initIndependentStat().registerStat();
080    
081        /** the amount of damage you've dealt */
082        public static StatBase damageDealtStat = (new StatBasic(2020, "stat.damageDealt")).registerStat();
083    
084        /** the amount of damage you have taken */
085        public static StatBase damageTakenStat = (new StatBasic(2021, "stat.damageTaken")).registerStat();
086    
087        /** the number of times you have died */
088        public static StatBase deathsStat = (new StatBasic(2022, "stat.deaths")).registerStat();
089    
090        /** the number of mobs you have killed */
091        public static StatBase mobKillsStat = (new StatBasic(2023, "stat.mobKills")).registerStat();
092    
093        /** counts the number of times you've killed a player */
094        public static StatBase playerKillsStat = (new StatBasic(2024, "stat.playerKills")).registerStat();
095        public static StatBase fishCaughtStat = (new StatBasic(2025, "stat.fishCaught")).registerStat();
096        public static StatBase[] mineBlockStatArray = initMinableStats("stat.mineBlock", 16777216);
097    
098        /** Tracks the number of items a given block or item has been crafted. */
099        public static StatBase[] objectCraftStats;
100    
101        /** Tracks the number of times a given block or item has been used. */
102        public static StatBase[] objectUseStats;
103    
104        /** Tracks the number of times a given block or item has been broken. */
105        public static StatBase[] objectBreakStats;
106        private static boolean blockStatsInitialized;
107        private static boolean itemStatsInitialized;
108    
109        /**
110         * This method simply NOPs. It is presumably used to call the static constructors on server start.
111         */
112        public static void nopInit() {}
113    
114        /**
115         * Initializes statistic fields related to breakable items and blocks.
116         */
117        public static void initBreakableStats()
118        {
119            objectUseStats = initUsableStats(objectUseStats, "stat.useItem", 16908288, 0, 256);
120            objectBreakStats = initBreakStats(objectBreakStats, "stat.breakItem", 16973824, 0, 256);
121            blockStatsInitialized = true;
122            initCraftableStats();
123        }
124    
125        public static void initStats()
126        {
127            objectUseStats = initUsableStats(objectUseStats, "stat.useItem", 16908288, 256, 32000);
128            objectBreakStats = initBreakStats(objectBreakStats, "stat.breakItem", 16973824, 256, 32000);
129            itemStatsInitialized = true;
130            initCraftableStats();
131        }
132    
133        /**
134         * Initializes statistics related to craftable items. Is only called after both block and item stats have been
135         * initialized.
136         */
137        public static void initCraftableStats()
138        {
139            if (blockStatsInitialized && itemStatsInitialized)
140            {
141                HashSet var0 = new HashSet();
142                Iterator var1 = CraftingManager.getInstance().getRecipeList().iterator();
143    
144                while (var1.hasNext())
145                {
146                    IRecipe var2 = (IRecipe)var1.next();
147    
148                    if (var2.getRecipeOutput() != null)
149                    {
150                        var0.add(Integer.valueOf(var2.getRecipeOutput().itemID));
151                    }
152                }
153    
154                var1 = FurnaceRecipes.smelting().getSmeltingList().values().iterator();
155    
156                while (var1.hasNext())
157                {
158                    ItemStack var4 = (ItemStack)var1.next();
159                    var0.add(Integer.valueOf(var4.itemID));
160                }
161    
162                objectCraftStats = new StatBase[32000];
163                var1 = var0.iterator();
164    
165                while (var1.hasNext())
166                {
167                    Integer var5 = (Integer)var1.next();
168    
169                    if (Item.itemsList[var5.intValue()] != null)
170                    {
171                        String var3 = StatCollector.translateToLocalFormatted("stat.craftItem", new Object[] {Item.itemsList[var5.intValue()].getStatName()});
172                        objectCraftStats[var5.intValue()] = (new StatCrafting(16842752 + var5.intValue(), var3, var5.intValue())).registerStat();
173                    }
174                }
175    
176                replaceAllSimilarBlocks(objectCraftStats);
177            }
178        }
179    
180        /**
181         * Initializes statistic fields related to minable items and blocks.
182         */
183        private static StatBase[] initMinableStats(String par0Str, int par1)
184        {
185            StatBase[] var2 = new StatBase[Block.blocksList.length];
186    
187            for (int var3 = 0; var3 < Block.blocksList.length; ++var3)
188            {
189                if (Block.blocksList[var3] != null && Block.blocksList[var3].getEnableStats())
190                {
191                    String var4 = StatCollector.translateToLocalFormatted(par0Str, new Object[] {Block.blocksList[var3].translateBlockName()});
192                    var2[var3] = (new StatCrafting(par1 + var3, var4, var3)).registerStat();
193                    objectMineStats.add((StatCrafting)var2[var3]);
194                }
195            }
196    
197            replaceAllSimilarBlocks(var2);
198            return var2;
199        }
200    
201        /**
202         * Initializes statistic fields related to usable items and blocks.
203         */
204        private static StatBase[] initUsableStats(StatBase[] par0ArrayOfStatBase, String par1Str, int par2, int par3, int par4)
205        {
206            if (par0ArrayOfStatBase == null)
207            {
208                par0ArrayOfStatBase = new StatBase[32000];
209            }
210    
211            for (int var5 = par3; var5 < par4; ++var5)
212            {
213                if (Item.itemsList[var5] != null)
214                {
215                    String var6 = StatCollector.translateToLocalFormatted(par1Str, new Object[] {Item.itemsList[var5].getStatName()});
216                    par0ArrayOfStatBase[var5] = (new StatCrafting(par2 + var5, var6, var5)).registerStat();
217    
218                    if (var5 >= 256)
219                    {
220                        itemStats.add((StatCrafting)par0ArrayOfStatBase[var5]);
221                    }
222                }
223            }
224    
225            replaceAllSimilarBlocks(par0ArrayOfStatBase);
226            return par0ArrayOfStatBase;
227        }
228    
229        private static StatBase[] initBreakStats(StatBase[] par0ArrayOfStatBase, String par1Str, int par2, int par3, int par4)
230        {
231            if (par0ArrayOfStatBase == null)
232            {
233                par0ArrayOfStatBase = new StatBase[32000];
234            }
235    
236            for (int var5 = par3; var5 < par4; ++var5)
237            {
238                if (Item.itemsList[var5] != null && Item.itemsList[var5].isDamageable())
239                {
240                    String var6 = StatCollector.translateToLocalFormatted(par1Str, new Object[] {Item.itemsList[var5].getStatName()});
241                    par0ArrayOfStatBase[var5] = (new StatCrafting(par2 + var5, var6, var5)).registerStat();
242                }
243            }
244    
245            replaceAllSimilarBlocks(par0ArrayOfStatBase);
246            return par0ArrayOfStatBase;
247        }
248    
249        /**
250         * Forces all dual blocks to count for each other on the stats list
251         */
252        private static void replaceAllSimilarBlocks(StatBase[] par0ArrayOfStatBase)
253        {
254            replaceSimilarBlocks(par0ArrayOfStatBase, Block.waterStill.blockID, Block.waterMoving.blockID);
255            replaceSimilarBlocks(par0ArrayOfStatBase, Block.lavaStill.blockID, Block.lavaStill.blockID);
256            replaceSimilarBlocks(par0ArrayOfStatBase, Block.pumpkinLantern.blockID, Block.pumpkin.blockID);
257            replaceSimilarBlocks(par0ArrayOfStatBase, Block.stoneOvenActive.blockID, Block.stoneOvenIdle.blockID);
258            replaceSimilarBlocks(par0ArrayOfStatBase, Block.oreRedstoneGlowing.blockID, Block.oreRedstone.blockID);
259            replaceSimilarBlocks(par0ArrayOfStatBase, Block.redstoneRepeaterActive.blockID, Block.redstoneRepeaterIdle.blockID);
260            replaceSimilarBlocks(par0ArrayOfStatBase, Block.torchRedstoneActive.blockID, Block.torchRedstoneIdle.blockID);
261            replaceSimilarBlocks(par0ArrayOfStatBase, Block.mushroomRed.blockID, Block.mushroomBrown.blockID);
262            replaceSimilarBlocks(par0ArrayOfStatBase, Block.stoneDoubleSlab.blockID, Block.stoneSingleSlab.blockID);
263            replaceSimilarBlocks(par0ArrayOfStatBase, Block.woodDoubleSlab.blockID, Block.woodSingleSlab.blockID);
264            replaceSimilarBlocks(par0ArrayOfStatBase, Block.grass.blockID, Block.dirt.blockID);
265            replaceSimilarBlocks(par0ArrayOfStatBase, Block.tilledField.blockID, Block.dirt.blockID);
266        }
267    
268        /**
269         * Forces stats for one block to add to another block, such as idle and active furnaces
270         */
271        private static void replaceSimilarBlocks(StatBase[] par0ArrayOfStatBase, int par1, int par2)
272        {
273            if (par0ArrayOfStatBase[par1] != null && par0ArrayOfStatBase[par2] == null)
274            {
275                par0ArrayOfStatBase[par2] = par0ArrayOfStatBase[par1];
276            }
277            else
278            {
279                allStats.remove(par0ArrayOfStatBase[par1]);
280                objectMineStats.remove(par0ArrayOfStatBase[par1]);
281                generalStats.remove(par0ArrayOfStatBase[par1]);
282                par0ArrayOfStatBase[par1] = par0ArrayOfStatBase[par2];
283            }
284        }
285    
286        @SideOnly(Side.CLIENT)
287        public static StatBase getOneShotStat(int par0)
288        {
289            return (StatBase)oneShotStats.get(Integer.valueOf(par0));
290        }
291    
292        static
293        {
294            AchievementList.init();
295            blockStatsInitialized = false;
296            itemStatsInitialized = false;
297        }
298    }