Ejemplo n.º 1
0
        private void _Save_Button_Click(object sender, EventArgs e)
        {
            DialogResult dr = DialogResult.Yes;

            if (_textChanged)
            {
                dr = MessageBox.Show("Changes to the script have been made, attempt to compile the script and save befor exiting?", "Save Changes?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
            }
            if (dr == DialogResult.Cancel) return;
            if (dr == DialogResult.No)
            {
                Close();
                return;
            }

            ExcelScript script = new ExcelScript(_fileManager);
            try
            {
                script.Compile(_scriptEditor_RichTextBox.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to compile script!\n\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

                dr = MessageBox.Show("Do you wish to still quit?", "Quit without saving?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (dr == DialogResult.No) return;
                if (dr == DialogResult.Yes)
                {
                    Close();
                    return;
                }
            }

            _dataGridViewCell.Value = _scriptEditor_RichTextBox.Text;
        }
Ejemplo n.º 2
0
        public static void TestAllExcelScripts()
        {
            ExcelScript.GlobalDebug(true);
            FileManager fileManager = new FileManager(Config.HglDir);
            fileManager.BeginAllDatReadAccess();
            fileManager.LoadTableFiles();
            fileManager.EndAllDatAccess();

            StringWriter results = new StringWriter();
            Dictionary<String, int> excelScriptDecompileFails = new Dictionary<String, int>();
            Dictionary<String, int> excelScriptRecompileFails = new Dictionary<String, int>();
            Dictionary<String, int> excelScriptComparisonFails = new Dictionary<String, int>();
            int grandTotalScripts = 0;
            int grandTotalScriptsDecompiled = 0;
            int grandTotalScriptsFailedDecompilation = 0;
            int grandTotalScriptsRecompiled = 0;
            int grandTotalScriptsFailedRecompilation = 0;
            int grandTotalScriptsCompared = 0;
            int grandTotalScriptsFailedComparison = 0;

            foreach (ExcelFile excelFile in fileManager.DataFiles.Values.Where(dataFile => dataFile.IsExcelFile))
            {
                String excelStringId = String.Format("{0}...", excelFile.StringId);
                Debug.Write(excelStringId);
                results.Write(excelStringId);

                //if (excelFile.StringId != "SKILLS") continue;

                if (excelFile.Delegator == null || excelFile.ScriptCode == null || excelFile.ScriptCode.Length == 0)
                {
                    Debug.WriteLine(" No script data");
                    results.WriteLine(" No script data");
                    continue;
                }

                String scriptIntValues = String.Format(" {0} script int values...", excelFile.ScriptCode.Length);
                Debug.WriteLine(scriptIntValues);
                results.WriteLine(scriptIntValues);

                StringWriter excelFileResults = new StringWriter();
                int colIndex = -1;
                int totalScriptsFound = 0;
                int totalScriptsDecompiled = 0;
                int totalScriptsFailedDecompilation = 0;
                int totalScriptsRecompiled = 0;
                int totalScriptsFailedRecompilation = 0;
                int totalScriptsCompared = 0;
                int totalScriptsFailedComparison = 0;

                foreach (FieldDelegate fieldDelegate in excelFile.Delegator)
                {
                    colIndex++;
                    ExcelAttributes excelAtributes = (ExcelAttributes)fieldDelegate.Info.GetCustomAttributes(typeof(ExcelAttributes), true).FirstOrDefault();
                    if (excelAtributes == null || !excelAtributes.IsScript) continue;

                    String currentColumn = String.Format("\tColumn[{0}] = {1}", colIndex, fieldDelegate.Name);
                    Debug.WriteLine(currentColumn);
                    results.WriteLine(currentColumn);
                    excelFileResults.WriteLine(currentColumn);

                    int rowIndex = -1;
                    int prevOffset = 0;
                    int scriptCount = 0;
                    int scriptsDecompiled = 0;
                    int scriptsFailedDecompilation = 0;
                    int scriptsRecompiled = 0;
                    int scriptsFailedRecompilation = 0;
                    int scriptsCompared = 0;
                    int scriptsFailedComparison = 0;
                    foreach (Object row in excelFile.Rows)
                    {
                        rowIndex++;
                        int byteOffset = (int)fieldDelegate.GetValue(row);
                        if (byteOffset == 0) continue;
                        Debug.Assert(byteOffset > prevOffset);
                        prevOffset = byteOffset;

                        if (byteOffset == 9649 && excelFile.StringId == "SKILLS") // todo: not sure what's with this script...
                        {
                            continue;
                        }

                        excelFileResults.WriteLine(String.Format("\t\tColumn({0}) = {3}, Row({1}), ByteOffset({2}):", colIndex, rowIndex, byteOffset, fieldDelegate.Name));
                        ExcelScript excelScript = new ExcelScript(fileManager);

                        scriptCount++;
                        String script;
                        int[] scriptCodes = excelFile.ReadScriptTable(byteOffset);
                        String scriptCodesStr = scriptCodes.ToString(",");
                        String semiDecompiledScript = _ReadScriptTable(excelScript, scriptCodes);

                        //if (scriptCodesStr == "707,0,714,666,0,3,201,673,603979779,26,5,2,284,0,0")
                        //{
                        //    int bp = 0;
                        //}

                        // test decompiling
                        try
                        {
                            script = excelScript.Decompile(excelFile.ScriptBuffer, byteOffset, scriptCodesStr, excelFile.StringId, rowIndex, colIndex, fieldDelegate.Name);
                            scriptsDecompiled++;
                        }
                        catch (Exception e)
                        {
                            if (!excelScriptDecompileFails.ContainsKey(excelFile.StringId))
                            {
                                excelScriptDecompileFails.Add(excelFile.StringId, 1);
                            }
                            else
                            {
                                excelScriptDecompileFails[excelFile.StringId]++;
                            }
                            scriptsFailedDecompilation++;
                            excelFileResults.WriteLine("Script Decompile Failed:\n" + semiDecompiledScript + "\n" + e + "\n");
                            continue;
                        }

                        // test compiling of decompiled script
                        int[] recompiledScriptCode;
                        try
                        {
                            ExcelScript excelScriptCompile = new ExcelScript(fileManager);
                            recompiledScriptCode = excelScriptCompile.Compile(script, scriptCodesStr, excelFile.StringId, rowIndex, colIndex, fieldDelegate.Name);
                            scriptsRecompiled++;
                        }
                        catch (Exception e)
                        {
                            if (!excelScriptRecompileFails.ContainsKey(excelFile.StringId))
                            {
                                excelScriptRecompileFails.Add(excelFile.StringId, 1);
                            }
                            else
                            {
                                excelScriptRecompileFails[excelFile.StringId]++;
                            }
                            scriptsFailedRecompilation++;
                            excelFileResults.WriteLine("Script Recompile Failed:\n" + semiDecompiledScript + "\n" + e + "\n");
                            continue;
                        }

                        // check recompiled fidelity
                        scriptsCompared++;
                        if (!scriptCodes.SequenceEqual(recompiledScriptCode))
                        {
                            if (!excelScriptComparisonFails.ContainsKey(excelFile.StringId))
                            {
                                excelScriptComparisonFails.Add(excelFile.StringId, 1);
                            }
                            else
                            {
                                excelScriptComparisonFails[excelFile.StringId]++;
                            }
                            scriptsFailedComparison++;
                            String compareFailed = String.Format("Script Comparison Failed:\nOriginal Script: {0} = {1}\nRecompiled Script: {2}\nSemi-Decompiled:\n{3}", scriptCodesStr, script, recompiledScriptCode.ToString(","), semiDecompiledScript);
                            excelFileResults.WriteLine(compareFailed);
                            continue;
                        }

                        excelFileResults.WriteLine(script + "\n");
                    }

                    totalScriptsFound += scriptCount;
                    totalScriptsDecompiled += scriptsDecompiled;
                    totalScriptsFailedDecompilation += scriptsFailedDecompilation;
                    totalScriptsRecompiled += scriptsRecompiled;
                    totalScriptsFailedRecompilation += scriptsFailedRecompilation;
                    totalScriptsCompared += scriptsCompared;
                    totalScriptsFailedComparison += scriptsFailedComparison;

                    String columnStats = String.Format("\t\t{0} scripts found, {1} scripts decompiled, {2} scripts failed to decompile.\n", scriptCount, scriptsDecompiled, scriptsFailedDecompilation);
                    columnStats += String.Format("\t\t\t{0} scripts recompiled, {1} scripts failed to recompile, {2} scripts compared, {3} scripts failed comparison",
                                                 scriptsRecompiled, scriptsFailedRecompilation, scriptsCompared, scriptsFailedComparison);
                    Debug.WriteLine(columnStats);
                    excelFileResults.WriteLine(columnStats);
                }

                grandTotalScripts += totalScriptsFound;
                grandTotalScriptsDecompiled += totalScriptsDecompiled;
                grandTotalScriptsFailedDecompilation += totalScriptsFailedDecompilation;
                grandTotalScriptsRecompiled += totalScriptsRecompiled;
                grandTotalScriptsFailedRecompilation += totalScriptsFailedRecompilation;
                grandTotalScriptsCompared += totalScriptsCompared;
                grandTotalScriptsFailedComparison += totalScriptsFailedComparison;

                String totalStats = String.Format("Totals: {0} scripts found, {1} scripts decompiled, {2} scripts failed to decompile.\n", totalScriptsFound, totalScriptsDecompiled, totalScriptsFailedDecompilation);
                totalStats += String.Format("\t{0} scripts recompiled, {1} scripts failed to recompile, {2} scripts compared, {3} scripts failed comparison",
                                            totalScriptsRecompiled, totalScriptsFailedRecompilation, totalScriptsCompared, totalScriptsFailedComparison);
                Debug.WriteLine(totalStats);
                results.WriteLine(totalStats);
                excelFileResults.WriteLine(totalStats);

                File.WriteAllText(@"C:\TestScripts\excelScripts_" + excelFile.StringId + ".txt", excelFileResults.ToString());
                excelFileResults.Close();
            }

            foreach (KeyValuePair<String, int> keyValuePair in excelScriptDecompileFails)
            {
                String excelFileFails = String.Format("{0} had {1} failed decompilation.", keyValuePair.Key, keyValuePair.Value);
                Debug.WriteLine(excelFileFails);
                results.WriteLine(excelFileFails);
            }

            String grandTotalStats = String.Format("Grand Totals: {0} scripts found, {1} scripts decompiled, {2} scripts failed to decompile.\n", grandTotalScripts, grandTotalScriptsDecompiled, grandTotalScriptsFailedDecompilation);
            grandTotalStats += String.Format("\t{0} scripts recompiled, {1} scripts failed to recompile, {2} scripts compared, {3} scripts failed comparison",
                                        grandTotalScriptsRecompiled, grandTotalScriptsFailedRecompilation, grandTotalScriptsCompared, grandTotalScriptsFailedComparison);
            Debug.WriteLine(grandTotalStats);
            results.WriteLine(grandTotalStats);

            File.WriteAllText(@"C:\TestScripts\excelScripts_Results.txt", results.ToString());
        }
Ejemplo n.º 3
0
 private void _TestCompile_Button_Click(object sender, EventArgs e)
 {
     ExcelScript script = new ExcelScript(_fileManager);
     try
     {
         script.Compile(_scriptEditor_RichTextBox.Text);
     }
     catch (Exception ex)
     {
         MessageBox.Show("Failed to compile script!\n\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
     }
 }
Ejemplo n.º 4
0
        private bool _ParseCSV(byte[] csvBytes, FileManager fileManager, Dictionary<String, ExcelFile> csvExcelFiles)
        {
            // function setup
            int stringBufferOffset = 0;
            int integerBufferOffset = 1;
            bool isProperties = (StringId == "PROPERTIES" || StringId == "_TCv4_PROPERTIES");
            ObjectDelegator objectDelegator;
            OutputAttribute[] excelAttributes;
            bool needOutputAttributes = true;

            if (fileManager == null || !fileManager.DataFileDelegators.ContainsKey(StringId))
            {
                FieldInfo[] fieldInfos = DataType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                fieldInfos = fieldInfos.OrderBy(f => f.MetadataToken).ToArray(); // order by defined order - GetFields does not guarantee ordering
                objectDelegator = new ObjectDelegator(fieldInfos);
                excelAttributes = new OutputAttribute[fieldInfos.Length];
            }
            else
            {
                objectDelegator = fileManager.DataFileDelegators[StringId];
                excelAttributes = new OutputAttribute[objectDelegator.FieldCount];
            }

            String[][] tableRows;
            if (csvBytes == null)
            {
                tableRows = _csvTable;
            }
            else
            {
                // get columns
                int offset = 0;
                int colCount = 1;
                while (csvBytes[offset++] != '\n') if (csvBytes[offset] == CSVDelimiter) colCount++;
                tableRows = FileTools.CSVToStringArray(csvBytes, colCount, CSVDelimiter);
            }

            int rowCount = tableRows.Length;
            String[] columns = tableRows[0];

            if (isProperties)
            {
                ExcelFunctions = new List<ExcelFunction>();
                _scriptBuffer = new byte[1]; // properties is weird - do this just to ensure 100% byte-for-byte accuracy
            }

            // parse file header - could use Regex here - but don't think that'd but faster, in fact, probably a lot slower(?) - meh
            // format: %s(%s) // first %s = StringId, second %s = FileHeader as String
            String fileHeader = columns[0];
            int fileHeaderStart = fileHeader.IndexOf("(") + 1;
            int fileHeaderEnd = fileHeader.IndexOf(")");
            String fileHeaderStr = fileHeader.Substring(fileHeaderStart, fileHeaderEnd - fileHeaderStart);
            _excelFileHeader = FileTools.StringToObject<ExcelHeader>(fileHeaderStr, ",", FileHeaderFields);

            String strId = fileHeader.Substring(0, fileHeader.IndexOf("(")).Trim(); // asking for exception lol
            Debug.Assert(strId == StringId);

            // Parse the tableRows
            bool failedParsing = false;
            Rows = new List<Object>();
            for (int row = 1; row < rowCount; row++)
            {
                int col = -1;
                int csvCol = 0;
                Object rowInstance = Activator.CreateInstance(DataType);
                foreach (ObjectDelegator.FieldDelegate fieldDelegate in objectDelegator)
                {
                    col++;

                    if (needOutputAttributes) excelAttributes[col] = GetExcelAttribute(fieldDelegate.Info);
                    OutputAttribute excelAttribute = excelAttributes[col];

                    // columns not present
                    if (!columns.Contains(fieldDelegate.Name))
                    {
                        // create row header object
                        if (fieldDelegate.FieldType == typeof(RowHeader))
                        {
                            String headerString = tableRows[row][csvCol++];
                            RowHeader rowHeader = FileTools.StringToObject<RowHeader>(headerString, ",", RowHeaderFields);
                            objectDelegator[fieldDelegate.Name, rowInstance] = rowHeader;
                            continue;
                        }

                        // assign default values
                        MarshalAsAttribute arrayMarshal = null;
                        Array arrayInstance = null;
                        if (fieldDelegate.FieldType.BaseType == typeof(Array))
                        {
                            arrayMarshal = (MarshalAsAttribute)fieldDelegate.Info.GetCustomAttributes(typeof(MarshalAsAttribute), false).First();
                            arrayInstance = (Array)Activator.CreateInstance(fieldDelegate.FieldType, arrayMarshal.SizeConst);
                            objectDelegator[fieldDelegate.Name, rowInstance] = arrayInstance;
                        }
                        else if (fieldDelegate.FieldType == typeof(String))
                        {
                            objectDelegator[fieldDelegate.Name, rowInstance] = String.Empty;
                        }

                        // assign constant non-zero values
                        if (excelAttribute == null || excelAttribute.ConstantValue == null) continue;
                        if (fieldDelegate.FieldType.BaseType == typeof(Array))
                        {
                            Debug.Assert(arrayInstance != null, "arrayInstance == null");
                            Debug.Assert(arrayMarshal != null, "arrayMarshal == null");

                            for (int i = 0; i < arrayMarshal.SizeConst; i++)
                            {
                                arrayInstance.SetValue(excelAttribute.ConstantValue, i);
                            }
                        }
                        else
                        {
                            objectDelegator[fieldDelegate.Name, rowInstance] = excelAttribute.ConstantValue;
                        }

                        continue;
                    }

                    // columns present
                    String value = tableRows[row][csvCol++];

                    if (fieldDelegate.Name == "code")
                    {
                        int code = (StringId == "REGION") ? int.Parse(value) : StringToCode(value);

                        if (fieldDelegate.FieldType == typeof(short))
                        {
                            objectDelegator[fieldDelegate.Name, rowInstance] = (short)code;
                        }
                        else
                        {
                            objectDelegator[fieldDelegate.Name, rowInstance] = code;
                        }

                        continue;
                    }

                    bool isArray = (fieldDelegate.FieldType.BaseType == typeof(Array));
                    bool isEnum = (fieldDelegate.FieldType.BaseType == typeof(Enum));
                    if (excelAttribute != null)
                    {
                        if (excelAttribute.IsTableIndex && fileManager != null)
                        {
                            int arraySize = 1;
                            if (isArray)
                            {
                                MarshalAsAttribute arrayMarshal = (MarshalAsAttribute)fieldDelegate.Info.GetCustomAttributes(typeof(MarshalAsAttribute), false).First();
                                arraySize = arrayMarshal.SizeConst;
                                Debug.Assert(arraySize > 0);
                            }

                            String[] indexStrs = value.Split(new[] { ',' });
                            Int32[] rowIndexValues = new int[arraySize];
                            for (int i = 0; i < arraySize; i++) rowIndexValues[i] = -1;

                            int maxElements = indexStrs.Length;
                            if (maxElements > arraySize)
                            {
                                Debug.WriteLine(String.Format("{0}: Loss of array elements detected. row = {1}, col = {2}.", StringId, row, col));
                                maxElements = arraySize;
                            }

                            for (int i = 0; i < maxElements; i++)
                            {
                                value = indexStrs[i];
                                if (value == "-1") continue;

                                String tableStringId = excelAttribute.TableStringId;
                                bool hasCodeColumn = fileManager.DataTableHasColumn(tableStringId, "code");
                                if (value.Length == 0 && hasCodeColumn) continue;

                                //LEVEL references multiple blank TREASURE row index values - all appear to be empty rows though, so meh...
                                //Debug.Assert(!String.IsNullOrEmpty(value));

                                int isNegative = 1;
                                if (value.Length > 0 && value[0] == '-')
                                {
                                    isNegative = -1;
                                    value = value.Substring(1, value.Length - 1);
                                }

                                int rowIndex = -1;
                                ExcelFile relatedExcel = null;
                                if (csvExcelFiles != null && csvExcelFiles.TryGetValue(tableStringId, out relatedExcel))
                                {
                                    rowIndex = relatedExcel._GetRowIndexFromValue(value, hasCodeColumn ? "code" : null);
                                }

                                if (relatedExcel == null)
                                {
                                    if (hasCodeColumn && value.Length <= 4)
                                    {
                                        int code = StringToCode(value);
                                        rowIndex = fileManager.GetExcelRowIndexFromStringId(tableStringId, code, "code");
                                    }
                                    else if (fileManager.DataTableHasColumn(tableStringId, "name"))
                                    {
                                        rowIndex = fileManager.GetExcelRowIndexFromStringId(tableStringId, value, "name");
                                    }
                                    else
                                    {
                                        rowIndex = fileManager.GetExcelRowIndex(tableStringId, value);
                                    }
                                }

                                rowIndexValues[i] = rowIndex * isNegative;
                            }

                            if (isArray)
                            {
                                objectDelegator[fieldDelegate.Name, rowInstance] = rowIndexValues;
                            }
                            else
                            {
                                objectDelegator[fieldDelegate.Name, rowInstance] = rowIndexValues[0];
                            }

                            continue;
                        }

                        if (excelAttribute.IsStringOffset)
                        {
                            if (_stringBuffer == null) _stringBuffer = new byte[1024];

                            if (String.IsNullOrEmpty(value))
                            {
                                objectDelegator[fieldDelegate.Name, rowInstance] = -1;
                                continue;
                            }

                            objectDelegator[fieldDelegate.Name, rowInstance] = stringBufferOffset;
                            FileTools.WriteToBuffer(ref _stringBuffer, ref stringBufferOffset, FileTools.StringToASCIIByteArray(value));
                            stringBufferOffset++; // \0
                            continue;
                        }

                        if (excelAttribute.IsScript)
                        {
                            if ((fileManager == null && value == "0") || value == "")
                            {
                                objectDelegator[fieldDelegate.Name, rowInstance] = 0;
                                continue;
                            }
                            if (_scriptBuffer == null)
                            {
                                _scriptBuffer = new byte[1024];
                                _scriptBuffer[0] = 0x00;
                            }

                            int[] scriptByteCode;
                            if (fileManager != null)
                            {
                                ExcelScript excelScript = new ExcelScript(fileManager);
                                scriptByteCode = excelScript.Compile(value, null, StringId, row, col, fieldDelegate.Name);
                            }
                            else
                            {
                                string[] splitValue = value.Split(',');
                                int count = splitValue.Length;
                                scriptByteCode = new int[count];
                                for (int i = 0; i < count; i++)
                                {
                                    scriptByteCode[i] = int.Parse(splitValue[i]);
                                }
                            }

                            objectDelegator[fieldDelegate.Name, rowInstance] = integerBufferOffset;
                            FileTools.WriteToBuffer(ref _scriptBuffer, ref integerBufferOffset, scriptByteCode.ToByteArray());
                            continue;
                        }

                        if (excelAttribute.IsSecondaryString)
                        {
                            if (SecondaryStrings == null) SecondaryStrings = new List<String>();

                            if (value == "")
                            {
                                objectDelegator[fieldDelegate.Name, rowInstance] = -1;
                                continue;
                            }
                            if (!SecondaryStrings.Contains(value))
                            {
                                SecondaryStrings.Add(value);
                            }

                            objectDelegator[fieldDelegate.Name, rowInstance] = SecondaryStrings.IndexOf(value);
                            continue;
                        }

                        if (excelAttribute.IsBitmask)
                        {
                            if (fieldDelegate.FieldType == typeof(UInt32))
                            {
                                objectDelegator[fieldDelegate.Name, rowInstance] = UInt32.Parse(value);
                                continue;
                            }

                            Object enumVal;
                            try
                            {
                                enumVal = Enum.Parse(fieldDelegate.FieldType, value);
                            }
                            catch (Exception)
                            {
                                String[] enumStrings = value.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                                String[] enumNames = Enum.GetNames(fieldDelegate.FieldType);
                                String enumString = String.Empty;

                                String enumSeperator = String.Empty;
                                foreach (String enumStr in enumStrings)
                                {
                                    if (!enumNames.Contains(enumStr))
                                    {
                                        Debug.WriteLine(String.Format("{0}: bitfield name '{1}' not found.", StringId, enumStr));
                                        continue;
                                    }

                                    enumString += enumSeperator + enumStr;
                                    enumSeperator = ",";
                                }

                                enumVal = enumString == "" ? 0 : Enum.Parse(fieldDelegate.FieldType, enumString);
                            }

                            objectDelegator[fieldDelegate.Name, rowInstance] = enumVal;
                            continue;
                        }
                    }

                    try
                    {
                        Object objValue;
                        if (isArray)
                        {
                            if (fieldDelegate.FieldType == typeof(Int32[]))
                            {
                                objValue = FileTools.StringToArray<Int32>(value, ",");
                            }
                            else
                            {
                                Type elementType = fieldDelegate.FieldType.GetElementType();
                                if (elementType.BaseType == typeof(Enum))
                                {
                                    String[] enumStrs = value.Split(new[] { ',' }, StringSplitOptions.None);
                                    Array enumsArray = Array.CreateInstance(elementType, enumStrs.Length);
                                    int i = 0;
                                    foreach (String enumStr in enumStrs)
                                    {
                                        enumsArray.SetValue(Enum.Parse(elementType, enumStr), i++);
                                    }
                                    objValue = enumsArray;
                                }
                                else
                                {
                                    throw new NotImplementedException("if (fieldInfo.FieldType.BaseType == typeof(Array)) :: Type = " + elementType.BaseType);
                                }
                            }

                            objectDelegator[fieldDelegate.Name, rowInstance] = objValue;
                        }
                        else if (isEnum)
                        {
                            object enumVal = Enum.Parse(fieldDelegate.FieldType, value);
                            objectDelegator[fieldDelegate.Name, rowInstance] = enumVal;
                        }
                        else
                        {
                            objValue = FileTools.StringToObject(value, fieldDelegate.FieldType);
                            objectDelegator[fieldDelegate.Name, rowInstance] = objValue;
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Critical Parsing Error: " + e);
                        failedParsing = true;
                        break;
                    }
                }
                if (failedParsing) break;
                needOutputAttributes = false;

                // applicable only for Unit type; items, missiles, monsters, objects, players
                if (Attributes.HasStats)
                {
                    if (StatsBuffer == null) StatsBuffer = new byte[rowCount - 1][];

                    String value = tableRows[row][csvCol];
                    String[] stringArray = value.Split(',');
                    byte[] byteArray = new byte[stringArray.Length];

                    for (int i = 0; i < byteArray.Length; i++)
                    {
                        byteArray[i] = Byte.Parse(stringArray[i]);
                    }
                    StatsBuffer[row - 1] = byteArray;
                }

                // properties has extra Scripts stuffs
                // yea, this is a bit messy, but it's a single table only and mostly done out of curiosity
                if (isProperties)
                {
                    String value = tableRows[row][csvCol];
                    String[] scripts = value.Split('\n');
                    ExcelFunction excelScript = new ExcelFunction();
                    if (scripts.Length > 1)
                    {
                        ExcelFunctions.Add(excelScript);
                    }

                    int i = 0;
                    do
                    {
                        if (scripts.Length == 1) continue;

                        i++;
                        String[] values = scripts[i].Split(',');
                        if (values.Length < 4) continue;

                        // script parameters
                        int typeValuesCount = values.Length - 3;
                        ExcelFunction.Parameter parameter = new ExcelFunction.Parameter
                        {
                            Name = values[0],
                            Unknown = UInt32.Parse(values[1]),
                            TypeId = UInt32.Parse(values[2]),
                            TypeValues = new int[typeValuesCount]
                        };

                        for (int j = 0; j < typeValuesCount; j++)
                        {
                            parameter.TypeValues[j] = Int32.Parse(values[3 + j]);
                        }

                        excelScript.Parameters.Add(parameter);

                    } while (i < scripts.Length - 1 - 2); // -2 for: last line is blank, and line before *might* be script values

                    // last line will be script values if it exists
                    if (i < scripts.Length - 2)
                    {
                        String[] values = scripts[++i].Split(',');
                        int[] scriptValues = new int[values.Length];

                        for (int j = 0; j < values.Length; j++)
                        {
                            scriptValues[j] = Int32.Parse(values[j]);
                        }

                        excelScript.ScriptByteCode = scriptValues.ToByteArray();
                    }
                }

                Rows.Add(rowInstance);
            }

            // resize the integer and string buffers if they were used
            if (_stringBuffer != null) Array.Resize(ref _stringBuffer, stringBufferOffset);
            if (_scriptBuffer != null) Array.Resize(ref _scriptBuffer, integerBufferOffset);

            return HasIntegrity = true;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Creates a ExcelFile based on the DataTable data.
        /// </summary>
        /// <param name="dataTable">The DataTable to read the data from.</param>
        /// <param name="fileManager">The FileManager to use for script compilations etc.</param>
        /// <returns>True if the DataTable parsed okay.</returns>
        public override bool ParseDataTable(DataTable dataTable, FileManager fileManager)
        {
            if (dataTable == null) throw new ArgumentNullException("dataTable", "DataTable can not be null!");
            if (fileManager == null) throw new ArgumentNullException("fileManager", "FileManager can not be null!");

            byte[] newStringBuffer = null;
            int newStringBufferOffset = 0;

            byte[] newScriptBuffer = (Attributes.HasScriptTable) ? new byte[1024] : null;
            int newScriptBufferOffset = 0; // don't start at 1 as it will resize the array wrong

            byte[][] newStatsBuffer = null;
            List<String> newSecondaryStrings = null;
            List<Object> newRows = new List<Object>();

            bool failedParsing = false;
            const BindingFlags bindingFlags = (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            FieldInfo[] dataFields = DataType.GetFields(bindingFlags);
            OutputAttribute[] excelAttributes;
            ObjectDelegator objectDelegator;

            if (fileManager == null || !fileManager.DataFileDelegators.ContainsKey(StringId))
            {
                FieldInfo[] fieldInfos = DataType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                objectDelegator = new ObjectDelegator(fieldInfos);
                excelAttributes = new OutputAttribute[fieldInfos.Length];
            }
            else
            {
                objectDelegator = fileManager.DataFileDelegators[StringId];
                excelAttributes = new OutputAttribute[objectDelegator.FieldCount];
            }

            for (int row = 0; row < dataTable.Rows.Count; row++)
            {
                int col = 1; // Skip the indice column (column 0)
                Object rowInstance = Activator.CreateInstance(DataType);
                foreach (ObjectDelegator.FieldDelegate fieldDelegate in objectDelegator)
                {
                    //if (fieldInfo.Name == "warpToFloor")
                    //{
                    //    int bp = 0;
                    //}

                    OutputAttribute attribute = GetExcelAttribute(fieldDelegate.Info);

                    // Initialize private fields
                    if (fieldDelegate.IsPrivate)
                    {
                        // will be in DataTable (first column)
                        if (fieldDelegate.FieldType == typeof(RowHeader))
                        {
                            String headerString = (String)dataTable.Rows[row][col++];
                            RowHeader rowHeader = FileTools.StringToObject<RowHeader>(headerString, ",", RowHeaderFields);
                            fieldDelegate.SetValue(rowInstance, rowHeader);
                            continue;
                        }

                        // will not be in DataTable
                        MarshalAsAttribute arrayMarshal = null;
                        Array arrayInstance = null;
                        if (fieldDelegate.FieldType.BaseType == typeof(Array))
                        {
                            arrayMarshal = (MarshalAsAttribute)fieldDelegate.Info.GetCustomAttributes(typeof(MarshalAsAttribute), false).First();
                            arrayInstance = (Array)Activator.CreateInstance(fieldDelegate.FieldType, arrayMarshal.SizeConst);
                            fieldDelegate.SetValue(rowInstance, arrayInstance);
                        }
                        else if (fieldDelegate.FieldType == typeof(String))
                        {
                            fieldDelegate.SetValue(rowInstance, String.Empty);
                        }

                        // assign constant non-zero values
                        if (attribute == null || attribute.ConstantValue == null) continue;
                        if (fieldDelegate.FieldType.BaseType == typeof(Array))
                        {
                            Debug.Assert(arrayInstance != null, "arrayInstance == null");
                            Debug.Assert(arrayMarshal != null, "arrayMarshal == null");

                            for (int i = 0; i < arrayMarshal.SizeConst; i++)
                            {
                                arrayInstance.SetValue(attribute.ConstantValue, i);
                            }
                        }
                        else
                        {
                            objectDelegator[fieldDelegate.Name, rowInstance] = attribute.ConstantValue;
                        }

                        continue;
                    }

                    // Public fields -> these are inside the datatable
                    Object value = dataTable.Rows[row][col++];
                    bool isArray = (fieldDelegate.FieldType.BaseType == typeof(Array));

                    if (attribute != null)
                    {
                        if (attribute.IsTableIndex)
                        {
                            if (isArray)
                            {
                                int arraySize = 1;
                                MarshalAsAttribute arrayMarshal = (MarshalAsAttribute)fieldDelegate.Info.GetCustomAttributes(typeof(MarshalAsAttribute), false).First();
                                arraySize = arrayMarshal.SizeConst;
                                Debug.Assert(arraySize > 0);

                                String strValue = value.ToString();

                                String[] indexStrs = strValue.Split(new[] { ',' });
                                Int32[] rowIndexValues = new int[arraySize];
                                for (int i = 0; i < arraySize; i++) rowIndexValues[i] = -1;

                                int maxElements = indexStrs.Length;
                                if (maxElements > arraySize)
                                {
                                    Debug.WriteLine(String.Format("{0}: Loss of array elements detected. row = {1}, col = {2}.", StringId, row, col));
                                    maxElements = arraySize;
                                }

                                int[] rowIndices = new int[maxElements];
                                for (int i = 0; i < maxElements; i++)
                                {
                                    rowIndices[i] = int.Parse(indexStrs[i]);
                                }

                                objectDelegator[fieldDelegate.Name, rowInstance] = rowIndices;
                            }
                            else
                            {
                                objectDelegator[fieldDelegate.Name, rowInstance] = int.Parse(value.ToString());
                            }

                            // we need to make sure the following data column is a relational column; some tables (and thus the relational column) aren't present, even though the column "links" to them (e.g. LEVEL_AREAS)
                            DataColumn dataColumn = dataTable.Columns[col];
                            if (dataColumn.ExtendedProperties.ContainsKey(ColumnTypeKeys.IsRelationGenerated) && (bool)dataColumn.ExtendedProperties[ColumnTypeKeys.IsRelationGenerated])
                            {
                                col++;
                            }

                            continue;
                        }

                        if (attribute.IsStringIndex)
                        {
                            fieldDelegate.SetValue(rowInstance, value);
                            col++; // Skip lookup
                            continue;
                        }

                        if (attribute.IsStringOffset)
                        {
                            String strValue = value as String;
                            if (strValue == null) throw new Exception("A script was not presented as a String!");

                            if (newStringBuffer == null)
                            {
                                newStringBuffer = new byte[1024];
                            }

                            if (String.IsNullOrEmpty(strValue)) // i.e. is empty
                            {
                                fieldDelegate.SetValue(rowInstance, -1);
                                continue;
                            }

                            fieldDelegate.SetValue(rowInstance, newStringBufferOffset);
                            FileTools.WriteToBuffer(ref newStringBuffer, ref newStringBufferOffset, FileTools.StringToASCIIByteArray(strValue));
                            FileTools.WriteToBuffer(ref newStringBuffer, ref newStringBufferOffset, (byte)0x00);
                            continue;
                        }

                        if (attribute.IsScript)
                        {
                            String strValue = value as String;

                            if (strValue == null || (fileManager == null && strValue == "0") || strValue == "")
                            {
                                objectDelegator[fieldDelegate.Name, rowInstance] = 0;
                                continue;
                            }

                            //if (strValue == "GetStat666('skill_points_bonus_total', '') > -1;")
                            //{
                            //    int bp = 0;
                            //}

                            int[] scriptByteCode;
                            int firstComma = -1; // is it an uncompiled int array
                            if (strValue[0] >= '0' && strValue[0] <= '9') firstComma = strValue.IndexOf(',');

                            if (fileManager != null && (firstComma == -1 || firstComma > 3)) // biggest opcode is 3 digits (this doesn't account for white space, but meh for now)
                            {
                                ExcelScript excelScript = new ExcelScript(fileManager);
                                scriptByteCode = excelScript.Compile(strValue);
                            }
                            else
                            {
                                scriptByteCode = strValue.ToArray<int>(',');
                            }

                            if (newScriptBufferOffset == 0) newScriptBufferOffset++; // 0 = no/null script
                            objectDelegator[fieldDelegate.Name, rowInstance] = newScriptBufferOffset;
                            FileTools.WriteToBuffer(ref newScriptBuffer, ref newScriptBufferOffset, scriptByteCode.ToByteArray());
                            continue;
                        }

                        if (attribute.IsSecondaryString)
                        {
                            if (newSecondaryStrings == null) newSecondaryStrings = new List<String>();

                            String strValue = value as String;
                            if (strValue == null) return false;

                            if (String.IsNullOrEmpty(strValue))
                            {
                                fieldDelegate.SetValue(rowInstance, -1);
                                continue;
                            }
                            if (newSecondaryStrings.Contains(strValue) == false)
                            {
                                newSecondaryStrings.Add(strValue);
                            }
                            fieldDelegate.SetValue(rowInstance, newSecondaryStrings.IndexOf(strValue));
                            continue;
                        }
                    }

                    try
                    {
                        if (fieldDelegate.FieldType != value.GetType()) // i.e. if the type hasn't been converted yet (no attributes means it wasn't converted above)
                        {
                            if (fieldDelegate.FieldType.BaseType == typeof(Enum))
                            {
                                value = Enum.Parse(fieldDelegate.FieldType, value.ToString());
                            }
                            else if (fieldDelegate.FieldType == typeof(Int32[]))
                            {
                                value = ((String)value).ToArray<Int32>(',');
                            }
                            else if (fieldDelegate.FieldType.BaseType == typeof(Array))
                            {
                                Type elementType = fieldDelegate.FieldType.GetElementType();
                                if (elementType.BaseType == typeof(Enum))
                                {
                                    String[] enumStrs = ((String)value).Split(new[] { ',' }, StringSplitOptions.None);
                                    Array enumsArray = Array.CreateInstance(elementType, enumStrs.Length);
                                    int i = 0;
                                    foreach (String enumStr in enumStrs)
                                    {
                                        enumsArray.SetValue(Enum.Parse(elementType, enumStr), i++);
                                    }
                                    value = enumsArray;
                                }
                                else
                                {
                                    throw new NotImplementedException("if (fieldInfo.FieldType.BaseType == typeof(Array)) :: Type = " + elementType.BaseType);
                                }
                            }
                            else
                            {
                                value = Convert.ChangeType(value, fieldDelegate.FieldType);
                            }
                        }

                        fieldDelegate.SetValue(rowInstance, value);
                    }
                    catch (Exception e)
                    {
                        ExceptionLogger.LogException(e);
                        Console.WriteLine("Critical Parsing Error: " + e.Message);
                        failedParsing = true;
                        break;
                    }
                }
                if (failedParsing) break;

                // For item types, items, missiles, monsters etc
                // This must be a hex byte delimited array
                if (Attributes.HasStats)
                {
                    if (newStatsBuffer == null)
                    {
                        newStatsBuffer = new byte[dataTable.Rows.Count][];
                    }
                    const char split = ',';
                    string value = dataTable.Rows[row][col] as string;
                    if (String.IsNullOrEmpty(value))
                    {
                        Console.WriteLine("Error parsing stats string.");
                        return false;
                    }
                    string[] stringArray = value.Split(split);
                    byte[] byteArray = new byte[stringArray.Length];
                    for (int i = 0; i < byteArray.Length; i++)
                    {
                        byteArray[i] = Byte.Parse(stringArray[i]);
                    }
                    newStatsBuffer[row] = byteArray;
                }

                newRows.Add(rowInstance);
            }

            // Parsing Complete, assign new references. These arn't assigned before now incase of a parsing error.
            Rows = newRows;

            _stringBuffer = newStringBuffer;
            if (_stringBuffer != null) Array.Resize(ref _stringBuffer, newStringBufferOffset);

            _scriptBuffer = newScriptBuffer;
            if (_scriptBuffer != null) Array.Resize(ref _scriptBuffer, newScriptBufferOffset);

            StatsBuffer = newStatsBuffer;
            SecondaryStrings = newSecondaryStrings;

            // assign file header details (they are not all the same!)
            ExcelHeader excelHeader = (ExcelHeader)dataTable.ExtendedProperties["FileHeader"];
            _excelFileHeader = excelHeader.DeepClone();

            return true;
        }