    001package net.minecraft.stats;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.ArrayList;
    006import java.util.HashMap;
    007import java.util.HashSet;
    008import java.util.Iterator;
    009import java.util.List;
    010import java.util.Map;
    011import net.minecraft.block.Block;
    012import net.minecraft.item.Item;
    013import net.minecraft.item.ItemStack;
    014import net.minecraft.item.crafting.CraftingManager;
    015import net.minecraft.item.crafting.FurnaceRecipes;
    016import net.minecraft.item.crafting.IRecipe;
    017import net.minecraft.util.StatCollector;
    018
    019public 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 hashset = new HashSet();
    142            Iterator iterator = CraftingManager.getInstance().getRecipeList().iterator();
    143
    144            while (iterator.hasNext())
    145            {
    146                IRecipe irecipe = (IRecipe)iterator.next();
    147
    148                if (irecipe.getRecipeOutput() != null)
    149                {
    150                    hashset.add(Integer.valueOf(irecipe.getRecipeOutput().itemID));
    151                }
    152            }
    153
    154            iterator = FurnaceRecipes.smelting().getSmeltingList().values().iterator();
    155
    156            while (iterator.hasNext())
    157            {
    158                ItemStack itemstack = (ItemStack)iterator.next();
    159                hashset.add(Integer.valueOf(itemstack.itemID));
    160            }
    161
    162            objectCraftStats = new StatBase[32000];
    163            iterator = hashset.iterator();
    164
    165            while (iterator.hasNext())
    166            {
    167                Integer integer = (Integer)iterator.next();
    168
    169                if (Item.itemsList[integer.intValue()] != null)
    170                {
    171                    String s = StatCollector.translateToLocalFormatted("stat.craftItem", new Object[] {Item.itemsList[integer.intValue()].getStatName()});
    172                    objectCraftStats[integer.intValue()] = (new StatCrafting(16842752 + integer.intValue(), s, integer.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[] astatbase = new StatBase[Block.blocksList.length];
    186
    187        for (int j = 0; j < Block.blocksList.length; ++j)
    188        {
    189            if (Block.blocksList[j] != null && Block.blocksList[j].getEnableStats())
    190            {
    191                String s1 = StatCollector.translateToLocalFormatted(par0Str, new Object[] {Block.blocksList[j].getLocalizedName()});
    192                astatbase[j] = (new StatCrafting(par1 + j, s1, j)).registerStat();
    193                objectMineStats.add((StatCrafting)astatbase[j]);
    194            }
    195        }
    196
    197        replaceAllSimilarBlocks(astatbase);
    198        return astatbase;
    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 l = par3; l < par4; ++l)
    212        {
    213            if (Item.itemsList[l] != null)
    214            {
    215                String s1 = StatCollector.translateToLocalFormatted(par1Str, new Object[] {Item.itemsList[l].getStatName()});
    216                par0ArrayOfStatBase[l] = (new StatCrafting(par2 + l, s1, l)).registerStat();
    217
    218                if (l >= 256)
    219                {
    220                    itemStats.add((StatCrafting)par0ArrayOfStatBase[l]);
    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 l = par3; l < par4; ++l)
    237        {
    238            if (Item.itemsList[l] != null && Item.itemsList[l].isDamageable())
    239            {
    240                String s1 = StatCollector.translateToLocalFormatted(par1Str, new Object[] {Item.itemsList[l].getStatName()});
    241                par0ArrayOfStatBase[l] = (new StatCrafting(par2 + l, s1, l)).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.furnaceBurning.blockID, Block.furnaceIdle.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}