    001package net.minecraft.crash;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.ArrayList;
    006import java.util.Iterator;
    007import java.util.List;
    008import java.util.concurrent.Callable;
    009import net.minecraft.util.MathHelper;
    010
    011public class CrashReportCategory
    012{
    013    private final CrashReport theCrashReport;
    014    private final String field_85076_b;
    015    private final List field_85077_c = new ArrayList();
    016    private StackTraceElement[] stackTrace = new StackTraceElement[0];
    017
    018    public CrashReportCategory(CrashReport par1CrashReport, String par2Str)
    019    {
    020        this.theCrashReport = par1CrashReport;
    021        this.field_85076_b = par2Str;
    022    }
    023
    024    @SideOnly(Side.CLIENT)
    025    public static String func_85074_a(double par0, double par2, double par4)
    026    {
    027        return String.format("%.2f,%.2f,%.2f - %s", new Object[] {Double.valueOf(par0), Double.valueOf(par2), Double.valueOf(par4), getLocationInfo(MathHelper.floor_double(par0), MathHelper.floor_double(par2), MathHelper.floor_double(par4))});
    028    }
    029
    030    /**
    031     * Returns a string with world information on location.Args:x,y,z
    032     */
    033    public static String getLocationInfo(int par0, int par1, int par2)
    034    {
    035        StringBuilder stringbuilder = new StringBuilder();
    036
    037        try
    038        {
    039            stringbuilder.append(String.format("World: (%d,%d,%d)", new Object[] {Integer.valueOf(par0), Integer.valueOf(par1), Integer.valueOf(par2)}));
    040        }
    041        catch (Throwable throwable)
    042        {
    043            stringbuilder.append("(Error finding world loc)");
    044        }
    045
    046        stringbuilder.append(", ");
    047        int l;
    048        int i1;
    049        int j1;
    050        int k1;
    051        int l1;
    052        int i2;
    053        int j2;
    054        int k2;
    055        int l2;
    056
    057        try
    058        {
    059            l = par0 >> 4;
    060            i1 = par2 >> 4;
    061            j1 = par0 & 15;
    062            k1 = par1 >> 4;
    063            l1 = par2 & 15;
    064            i2 = l << 4;
    065            j2 = i1 << 4;
    066            k2 = (l + 1 << 4) - 1;
    067            l2 = (i1 + 1 << 4) - 1;
    068            stringbuilder.append(String.format("Chunk: (at %d,%d,%d in %d,%d; contains blocks %d,0,%d to %d,255,%d)", new Object[] {Integer.valueOf(j1), Integer.valueOf(k1), Integer.valueOf(l1), Integer.valueOf(l), Integer.valueOf(i1), Integer.valueOf(i2), Integer.valueOf(j2), Integer.valueOf(k2), Integer.valueOf(l2)}));
    069        }
    070        catch (Throwable throwable1)
    071        {
    072            stringbuilder.append("(Error finding chunk loc)");
    073        }
    074
    075        stringbuilder.append(", ");
    076
    077        try
    078        {
    079            l = par0 >> 9;
    080            i1 = par2 >> 9;
    081            j1 = l << 5;
    082            k1 = i1 << 5;
    083            l1 = (l + 1 << 5) - 1;
    084            i2 = (i1 + 1 << 5) - 1;
    085            j2 = l << 9;
    086            k2 = i1 << 9;
    087            l2 = (l + 1 << 9) - 1;
    088            int i3 = (i1 + 1 << 9) - 1;
    089            stringbuilder.append(String.format("Region: (%d,%d; contains chunks %d,%d to %d,%d, blocks %d,0,%d to %d,255,%d)", new Object[] {Integer.valueOf(l), Integer.valueOf(i1), Integer.valueOf(j1), Integer.valueOf(k1), Integer.valueOf(l1), Integer.valueOf(i2), Integer.valueOf(j2), Integer.valueOf(k2), Integer.valueOf(l2), Integer.valueOf(i3)}));
    090        }
    091        catch (Throwable throwable2)
    092        {
    093            stringbuilder.append("(Error finding world loc)");
    094        }
    095
    096        return stringbuilder.toString();
    097    }
    098
    099    /**
    100     * Adds a Crashreport section with the given name with the value set to the result of the given Callable;
    101     */
    102    public void addCrashSectionCallable(String par1Str, Callable par2Callable)
    103    {
    104        try
    105        {
    106            this.addCrashSection(par1Str, par2Callable.call());
    107        }
    108        catch (Throwable throwable)
    109        {
    110            this.addCrashSectionThrowable(par1Str, throwable);
    111        }
    112    }
    113
    114    /**
    115     * Adds a Crashreport section with the given name with the given value (convered .toString())
    116     */
    117    public void addCrashSection(String par1Str, Object par2Obj)
    118    {
    119        this.field_85077_c.add(new CrashReportCategoryEntry(par1Str, par2Obj));
    120    }
    121
    122    /**
    123     * Adds a Crashreport section with the given name with the given Throwable
    124     */
    125    public void addCrashSectionThrowable(String par1Str, Throwable par2Throwable)
    126    {
    127        this.addCrashSection(par1Str, par2Throwable);
    128    }
    129
    130    public int func_85073_a(int par1)
    131    {
    132        StackTraceElement[] astacktraceelement = Thread.currentThread().getStackTrace();
    133        //BugFix: Causes AIOOB for stacks < 3 + par1
    134        int len = astacktraceelement.length - 3 - par1;
    135        if (len <= 0) len = astacktraceelement.length;
    136        this.stackTrace = new StackTraceElement[len];
    137        System.arraycopy(astacktraceelement, astacktraceelement.length - len, this.stackTrace, 0, this.stackTrace.length);
    138        return this.stackTrace.length;
    139    }
    140
    141    public boolean func_85069_a(StackTraceElement par1StackTraceElement, StackTraceElement par2StackTraceElement)
    142    {
    143        if (this.stackTrace.length != 0 && par1StackTraceElement != null)
    144        {
    145            StackTraceElement stacktraceelement2 = this.stackTrace[0];
    146
    147            if (stacktraceelement2.isNativeMethod() == par1StackTraceElement.isNativeMethod() && stacktraceelement2.getClassName().equals(par1StackTraceElement.getClassName()) && stacktraceelement2.getFileName().equals(par1StackTraceElement.getFileName()) && stacktraceelement2.getMethodName().equals(par1StackTraceElement.getMethodName()))
    148            {
    149                if (par2StackTraceElement != null != this.stackTrace.length > 1)
    150                {
    151                    return false;
    152                }
    153                else if (par2StackTraceElement != null && !this.stackTrace[1].equals(par2StackTraceElement))
    154                {
    155                    return false;
    156                }
    157                else
    158                {
    159                    this.stackTrace[0] = par1StackTraceElement;
    160                    return true;
    161                }
    162            }
    163            else
    164            {
    165                return false;
    166            }
    167        }
    168        else
    169        {
    170            return false;
    171        }
    172    }
    173
    174    public void func_85070_b(int par1)
    175    {
    176        StackTraceElement[] astacktraceelement = new StackTraceElement[this.stackTrace.length - par1];
    177        System.arraycopy(this.stackTrace, 0, astacktraceelement, 0, astacktraceelement.length);
    178        this.stackTrace = astacktraceelement;
    179    }
    180
    181    public void func_85072_a(StringBuilder par1StringBuilder)
    182    {
    183        par1StringBuilder.append("-- ").append(this.field_85076_b).append(" --\n");
    184        par1StringBuilder.append("Details:");
    185        Iterator iterator = this.field_85077_c.iterator();
    186
    187        while (iterator.hasNext())
    188        {
    189            CrashReportCategoryEntry crashreportcategoryentry = (CrashReportCategoryEntry)iterator.next();
    190            par1StringBuilder.append("\n\t");
    191            par1StringBuilder.append(crashreportcategoryentry.func_85089_a());
    192            par1StringBuilder.append(": ");
    193            par1StringBuilder.append(crashreportcategoryentry.func_85090_b());
    194        }
    195
    196        if (this.stackTrace != null && this.stackTrace.length > 0)
    197        {
    198            par1StringBuilder.append("\nStacktrace:");
    199            StackTraceElement[] astacktraceelement = this.stackTrace;
    200            int i = astacktraceelement.length;
    201
    202            for (int j = 0; j < i; ++j)
    203            {
    204                StackTraceElement stacktraceelement = astacktraceelement[j];
    205                par1StringBuilder.append("\n\tat ");
    206                par1StringBuilder.append(stacktraceelement.toString());
    207            }
    208        }
    209    }
    210
    211    public static void func_85068_a(CrashReportCategory par0CrashReportCategory, int par1, int par2, int par3, int par4, int par5)
    212    {
    213        par0CrashReportCategory.addCrashSectionCallable("Block type", new CallableBlockType(par4));
    214        par0CrashReportCategory.addCrashSectionCallable("Block data value", new CallableBlockDataValue(par5));
    215        par0CrashReportCategory.addCrashSectionCallable("Block location", new CallableBlockLocation(par1, par2, par3));
    216    }
    217}