public XmlCookedElement(XmlCookedAttribute xmlAttribute, ObjectDelegator.FieldDelegate fieldDelegate)
 {
     XmlAttribute = xmlAttribute;
     FieldDelegate = fieldDelegate;
 }
Beispiel #2
0
        public static ObjectDelegator GetExcelDelegator(DataFile excelFile, IDictionary<String, ObjectDelegator> objectDelegators)
        {
            ObjectDelegator excelDelegator;

            if (!objectDelegators.TryGetValue(excelFile.StringId, out excelDelegator))
            {
                Type rowType = excelFile.Attributes.RowType;
                FieldInfo[] fieldInfos = rowType.GetFields();

                excelDelegator = new ObjectDelegator(fieldInfos);

                objectDelegators.Add(excelFile.StringId, excelDelegator);
            }

            return excelDelegator;
        }
Beispiel #3
0
        public static void TestAllCodeValues()
        {
            FileManager fileManager = new FileManager(Config.HglDir);
            fileManager.LoadTableFiles();

            int fileCountWithCode = 0;
            foreach (DataFile dataFile in fileManager.DataFiles.Values)
            {
                if (!dataFile.IsExcelFile) continue;

                ExcelFile excelFile = (ExcelFile)dataFile;

                Debug.Write(String.Format("Checking code fields within file {0}... ", excelFile.StringId));

                FieldInfo[] fieldInfos = excelFile.Attributes.RowType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                FieldInfo[] codeFields = (from fi in fieldInfos
                                          where fi.Name == "code"
                                          select fi).ToArray();

                if (codeFields.Length == 0)
                {
                    Debug.WriteLine("None found.");
                    continue;
                }

                //if (excelFile.StringId == "ACT")
                //{
                //    int bp = 0;

                //    ExcelFile.Code codeObj = new ExcelFile.Code();
                //    codeObj = "AAB";

                //    int codeInt = codeObj;
                //}

                Debug.Assert(codeFields.Length == 1);
                Debug.WriteLine(String.Format("{0} fields found.", codeFields.Length));
                fileCountWithCode++;

                ObjectDelegator objectDelegator = new ObjectDelegator(codeFields);

                Debug.WriteLine("Codes found: ");
                foreach (FieldInfo fieldInfo in codeFields)
                {
                    foreach (Object row in excelFile.Rows)
                    {
                        int code = 0;
                        if (fieldInfo.FieldType == typeof(short))
                        {
                            code = (int)(short)objectDelegator["code"](row);
                        }
                        //else if (fieldInfo.FieldType == typeof(ExcelFile.Code))
                        //{
                        //    code = (ExcelFile.Code)objectDelegator["code"](row);
                        //}
                        //else if (fieldInfo.FieldType == typeof(ExcelFile.ShortCode))
                        //{
                        //    code = (ExcelFile.ShortCode)objectDelegator["code"](row);
                        //}
                        else
                        {
                            code = (int)objectDelegator["code"](row);
                        }

                        if (code == 0) continue;

                        char char1 = (char)(code & 0xFF);
                        char char2 = (char)((code & 0xFF00) >> 8);
                        char char3 = (char)((code & 0xFF0000) >> 16);
                        char char4 = (char)((code & 0xFF000000) >> 24);

                        Debug.Assert(_CharCodeCharValue(char1));
                        Debug.Assert(_CharCodeCharValue(char2));
                        Debug.Assert(_CharCodeCharValue(char3));
                        Debug.Assert(_CharCodeCharValue(char4));

                        Debug.Write(String.Format(" {0}{1}{2}{3}", char1, char2, char3, char4));
                    }
                }

                Debug.WriteLine("");
            }

            Debug.WriteLine(String.Format("{0} files with code fields checked.", fileCountWithCode));
        }
Beispiel #4
0
        /// <summary>
        /// Function to conver the TCv4 excel files to SP client formats.
        /// </summary>
        public static void ConvertTCv4ExcelToSP()
        {
            // init file manager and load excel files
            FileManager fileManager = new FileManager(Config.HglDir);
            fileManager.ExtractAllExcel();
            FileManager fileManagerTCv4 = new FileManager(Config.HglDir, FileManager.ClientVersions.TestCenter);

            fileManager.LoadTableFiles();
            fileManagerTCv4.LoadTableFiles(true);

            if (fileManager.DataFiles.Count == 0)
            {
                Debug.WriteLine("Error: No Excel files loaded!");
                return;
            }
            if (fileManagerTCv4.DataFiles.Count == 0)
            {
                Debug.WriteLine("Error: No TCv4 Excel files loaded!");
                return;
            }

            // convert tables
            //int converted = -1;
            Dictionary<String, ObjectDelegator> objectDelegators = new Dictionary<String, ObjectDelegator>();
            foreach (ExcelFile excelFile in fileManager.DataFiles.Values.Where(dataFile => dataFile.IsExcelFile))
            {
                //if (++converted >= 5) break;

                Debug.WriteLine("Converting Excel table " + excelFile.StringId + "...");

                // obviously don't want to convert this one
                if (excelFile.StringId == "EXCELTABLES") continue;

                // we can't convert stats as some index entries are hard-coded...
                if (excelFile.StringId == "STATS") continue;

                // game crashes with this converted...
                if (excelFile.StringId == "UNITMODES") continue;

                // don't bother with these two as there's no TCv4 equivalent (they don't matter anyways)
                if (excelFile.StringId == "LANGUAGE" || excelFile.StringId == "REGION") continue;

                // ensure we have a TCv4 version loaded
                String stringIdTCv4 = "_TCv4_" + excelFile.StringId;
                ExcelFile excelFileTCv4 = (ExcelFile)fileManagerTCv4.GetDataFile(stringIdTCv4);
                if (excelFileTCv4 == null)
                {
                    Debug.WriteLine("Error: TCv4 Excel file not found: " + stringIdTCv4);
                    continue;
                }

                // table specialisation stuffs
                bool isAchievements = false;
                bool isAffixes = false;
                bool isCharacterClass = false;
                //bool isCharDisplay = false;
                //bool isInventory = false;
                switch (excelFile.StringId)
                {
                    case "ACHIEVEMENTS":
                        isAchievements = true;
                        break;

                    case "AFFIXES":
                        isAffixes = true;
                        break;

                    case "CHARACTER_CLASS":
                        isCharacterClass = true;
                        break;

                    //case "CHARDISPLAY":
                    //    isCharDisplay = true;
                    //    break;

                    //case "INVENTORY":
                    //    isInventory = true;
                    //    break;
                }

                // genereal type-init stuffs; get our object delegators
                ObjectDelegator excelDelegator;
                ObjectDelegator excelDelegatorTCv41;
                ObjectDelegator excelDelegatorTCv42 = null;
                Type rowType = excelFile.Attributes.RowType;
                Type rowTypeTCv41 = excelFileTCv4.Attributes.RowType;
                Type rowTypeTCv42 = null;
                FieldInfo[] fieldInfos = rowType.GetFields();
                FieldInfo[] fieldInfosTCv41 = rowTypeTCv41.GetFields();
                FieldInfo[] fieldInfosTCv42 = null;

                // need to copy row headers (private field) as well
                FieldInfo rowHeaderField = rowType.GetField("header", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                FieldInfo rowHeaderFieldTCv4 = rowTypeTCv41.GetField("header", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                Array.Resize(ref fieldInfos, fieldInfos.Length + 1);
                Array.Resize(ref fieldInfosTCv41, fieldInfosTCv41.Length + 1);
                fieldInfos[fieldInfos.Length - 1] = rowHeaderField;
                fieldInfosTCv41[fieldInfosTCv41.Length - 1] = rowHeaderFieldTCv4;

                // create delegates
                if (!objectDelegators.TryGetValue(excelFile.StringId, out excelDelegator))
                {
                    excelDelegator = new ObjectDelegator(fieldInfos);
                    objectDelegators.Add(excelFile.StringId, excelDelegator);
                }
                if (!objectDelegators.TryGetValue(stringIdTCv4, out excelDelegatorTCv41))
                {
                    excelDelegatorTCv41 = new ObjectDelegator(fieldInfosTCv41);
                    objectDelegators.Add(stringIdTCv4, excelDelegatorTCv41);
                }

                // table specialisation inititialisation
                //// achievements
                Dictionary<int, int> unitTypeOverflow = null;
                if (isAchievements)
                {
                    unitTypeOverflow = new Dictionary<int, int>();
                }

                //// affixes
                ExcelFile affixGroupsTable = null;
                List<String> affixGroupsList = null;
                List<Int32> affixGroupWeightScripts = null;
                if (isAffixes)
                {
                    affixGroupsTable = fileManagerTCv4.GetDataFile("_TCv4_AFFIX_GROUPS") as ExcelFile;
                    affixGroupsList = new List<String>();
                    affixGroupWeightScripts = new List<Int32>();
                    Debug.Assert(affixGroupsTable != null);

                    rowTypeTCv42 = affixGroupsTable.Attributes.RowType;
                    fieldInfosTCv42 = rowTypeTCv42.GetFields();

                    FieldInfo rowHeaderFieldTCv42 = rowTypeTCv42.GetField("header", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                    Array.Resize(ref fieldInfosTCv42, fieldInfosTCv42.Length + 1);
                    fieldInfosTCv42[fieldInfosTCv42.Length - 1] = rowHeaderFieldTCv42;

                    excelDelegatorTCv42 = new ObjectDelegator(fieldInfosTCv42);
                }

                // debug: ensure we have same columns
                if (!isAchievements && !isCharacterClass && !isAffixes)
                {
                    bool hasSameFields = true;
                    foreach (FieldInfo fieldInfo in fieldInfos)
                    {
                        FieldInfo fieldInfoTCv4 = (from fi in fieldInfosTCv41
                                                   where fi.Name == fieldInfo.Name
                                                   select fi).FirstOrDefault();
                        if (fieldInfoTCv4 == null)
                        {
                            Debug.WriteLine("Field not found in TCv4 table: " + fieldInfo.Name);
                            hasSameFields = false;
                            continue;
                        }

                        if (fieldInfo.FieldType == fieldInfoTCv4.FieldType || fieldInfo.FieldType.BaseType == typeof(Enum)) continue;
                        Debug.WriteLine(String.Format("FieldInfo '{0}' of type '{1}' does not match TCv4 of type '{2}'", fieldInfo.Name, fieldInfo.FieldType, fieldInfoTCv4.FieldType));
                        hasSameFields = false;
                    }

                    if (!hasSameFields)
                    {
                        Debug.WriteLine("Error: The Excel types do not have the same fields!");
                        continue;
                    }
                }

                // begin conversion process
                Object[] rows = new Object[excelFileTCv4.Rows.Count];
                bool failed = false;
                int col = -1;
                byte[] scriptBuffer = new byte[1024];
                int scriptBufferOffset = 1; // first byte is null
                foreach (FieldInfo fieldInfo in fieldInfos) // loop by column
                {
                    col++;

                    ObjectDelegator.FieldGetValueDelegate getTCv4Value1 = null;
                    ObjectDelegator.FieldGetValueDelegate getTCv4Value2 = null;
                    ObjectDelegator.FieldGetValueDelegate getTCv4Value3 = null;
                    ObjectDelegator.FieldSetValueDelegate setValue1 = excelDelegator.GetFieldSetDelegate(fieldInfo.Name);
                    ObjectDelegator.FieldSetValueDelegate setValue2 = null;
                    ObjectDelegator.FieldGetValueDelegate getValue = excelDelegator.GetFieldGetDelegate(fieldInfo.Name);
                    ExcelFile.OutputAttribute outputAttribute = ExcelFile.GetExcelAttribute(fieldInfo);

                    // table specialisation stuffs
                    bool isUnitTypeField = false;                       // achievements
                    bool isItemField = false;                           // achievements
                    bool isUnitVersionToGetSkillRespec = false;         // character class
                    bool isGroup = false;                               // affixes
                    if (isAchievements && (fieldInfo.Name.StartsWith("unitType") || fieldInfo.Name == "item"))
                    {
                        if (fieldInfo.Name.StartsWith("unitType"))
                        {
                            String monsterFieldName = "monsterUnitType" + fieldInfo.Name.Last();
                            String itemFieldName = "itemUnitType" + fieldInfo.Name.Last();

                            getTCv4Value1 = excelDelegatorTCv41.GetFieldGetDelegate(monsterFieldName);
                            getTCv4Value2 = excelDelegatorTCv41.GetFieldGetDelegate(itemFieldName);
                            isUnitTypeField = true;
                        }
                        else if (fieldInfo.Name == "item")
                        {
                            isItemField = true;
                        }
                    }
                    else if (isCharacterClass && fieldInfo.Name == "unitVersionToGetSkillRespec")
                    {
                        isUnitVersionToGetSkillRespec = true;
                    }
                    else if (isAffixes && (fieldInfo.Name == "group" || fieldInfo.Name == "groupWeight"))
                    {
                        if (fieldInfo.Name == "groupWeight") continue; // we can skip it as we're setting it during group column

                        getTCv4Value1 = excelDelegatorTCv41.GetFieldGetDelegate(fieldInfo.Name);    // to get group affix index
                        getTCv4Value2 = excelDelegatorTCv42.GetFieldGetDelegate("name");            // to get group affix name
                        getTCv4Value3 = excelDelegatorTCv42.GetFieldGetDelegate("weight");          // to get group affix weight
                        setValue2 = excelDelegator.GetFieldSetDelegate("groupWeight");              // to set group weight
                        isGroup = true;
                    }
                    else
                    {
                        getTCv4Value1 = excelDelegatorTCv41.GetFieldGetDelegate(fieldInfo.Name);
                    }

                    // copy/convert field data
                    int row = -1;
                    foreach (Object rowTCv4 in excelFileTCv4.Rows) // loop by row
                    {
                        if (rows[++row] == null) rows[row] = Activator.CreateInstance(excelFile.Attributes.RowType);

                        Object value;

                        // achievements special stuffs
                        if (isAchievements && (isUnitTypeField || isItemField))
                        {
                            if (isUnitTypeField)
                            {
                                int monsterValue = (int)getTCv4Value1(rowTCv4);
                                int itemValue = (int)getTCv4Value2(rowTCv4);

                                if (monsterValue != 0 && itemValue != 0)
                                {
                                    Debug.Assert(!unitTypeOverflow.ContainsKey(row));

                                    unitTypeOverflow.Add(row, itemValue);
                                    itemValue = 0;
                                }
                                else if (monsterValue == 0 && itemValue == 0 && unitTypeOverflow.ContainsKey(row))
                                {
                                    itemValue = unitTypeOverflow[row];
                                    unitTypeOverflow.Remove(row);
                                }

                                value = (itemValue == 0) ? monsterValue : itemValue;
                            }
                            else
                            {
                                value = 0;
                            }
                        }
                        else if (isCharacterClass && isUnitVersionToGetSkillRespec)
                        {
                            value = getValue(excelFile.Rows[row]);
                        }
                        else if (isAffixes && isGroup)
                        {
                            Debug.Assert(getTCv4Value1 != null && getTCv4Value2 != null && getTCv4Value3 != null);

                            int affixGroupRowIndex = (int)getTCv4Value1(rowTCv4);

                            if (affixGroupRowIndex == -1)
                            {
                                setValue2(rows[row], 0);
                                value = -1;
                            }
                            else
                            {
                                int affixGroupStringOffset = (int)getTCv4Value2(affixGroupsTable.Rows[affixGroupRowIndex]);
                                int affixGroupWeight = (int)getTCv4Value3(affixGroupsTable.Rows[affixGroupRowIndex]);

                                setValue2(rows[row], scriptBufferOffset);
                                FileTools.WriteToBuffer(ref scriptBuffer, ref scriptBufferOffset, new[] { (Int32)ExcelScript.ScriptOpCodes.Push, affixGroupWeight, 0 }.ToByteArray());

                                String affixGroupString = affixGroupsTable.ReadStringTable(affixGroupStringOffset);
                                int affixGroupStringIndex = affixGroupsList.IndexOf(affixGroupString);
                                if (affixGroupStringIndex == -1)
                                {
                                    affixGroupStringIndex = affixGroupsList.Count;
                                    affixGroupsList.Add(affixGroupString);
                                }

                                value = affixGroupStringIndex;
                            }
                        }
                        else
                        {
                            Debug.Assert(getTCv4Value1 != null);

                            value = getTCv4Value1(rowTCv4);
                        }

                        if (outputAttribute == null)
                        {
                            setValue1(rows[row], value);
                            continue;
                        }

                        if (outputAttribute.IsBitmask)
                        {
                            if (value.GetType().BaseType != typeof(Enum))
                            {
                                Debug.WriteLine("Error: IsBitmask is not of type Enum: " + fieldInfo.Name);
                                failed = true;
                                break;
                            }

                            Type spBitMask = fieldInfo.FieldType;
                            Type tcBitMask = value.GetType();
                            uint currentMask = (uint)value;
                            uint convertedMask = 0;

                            for (int i = 0; i < 32; i++)
                            {
                                uint testBit = (uint)1 << i;
                                if ((currentMask & testBit) == 0) continue;

                                String bitString = Enum.GetName(tcBitMask, testBit);
                                if (bitString == null) continue;

                                if (Enum.IsDefined(spBitMask, bitString))
                                {
                                    convertedMask += (uint)Enum.Parse(spBitMask, bitString);
                                }
                            }

                            value = convertedMask;
                        }
                        else if (outputAttribute.IsScript)
                        {
                            //int scriptOffset = (int)value;
                            //if (scriptOffset != 0)
                            //{
                            //    ExcelScript excelScriptTCv4 = new ExcelScript(fileManagerTCv4);

                            //    try
                            //    {
                            //        excelScriptTCv4.Decompile(excelFileTCv4.ScriptBuffer, scriptOffset, null, excelFileTCv4.StringId, row, col, fieldInfo.Name);
                            //    }
                            //    catch (Exception e)
                            //    {
                            //        Debug.WriteLine("TCv4 Decompile Error:\n" + e);
                            //        continue;
                            //    }

                            //    ExcelScript excelScriptCompiler = new ExcelScript(fileManagerTCv4, true, true);

                            //    try
                            //    {
                            //        excelScriptCompiler.Compile(excelScriptTCv4.ScriptString, null, excelFileTCv4.StringId, row, col, fieldInfo.Name);
                            //        value = scriptBufferOffset;
                            //    }
                            //    catch (Exceptions.ScriptUnknownFunctionException e)
                            //    {
                            //        if (isCharDisplay || isInventory)
                            //        {
                            //            value = 0;
                            //        }
                            //        else
                            //        {
                            //            Debug.WriteLine("SP Recompile Error: \n" + excelScriptTCv4.ScriptString + "\n" + e);
                            //            value = 0;
                            //            //continue;
                            //        }
                            //    }
                            //    catch (Exception e)
                            //    {
                            //        Debug.WriteLine("SP Recompile Error: \n" + excelScriptTCv4.ScriptString + "\n" + e);
                            //        value = 0;
                            //        //continue;
                            //    }

                            //    if ((int)value != 0)
                            //    {
                            //        FileTools.WriteToBuffer(ref scriptBuffer, ref scriptBufferOffset, excelScriptCompiler.ScriptCode.ToByteArray());
                            //    }
                            //}
                        }

                        setValue1(rows[row], value);
                    }

                    if (failed) break;
                }
                if (failed)
                {
                    Debug.WriteLine("Error: Excel conversion failed: " + excelFile.StringId);
                    continue;
                }

                // finish conversion process by "changing" the TCv4 type
                excelFileTCv4.ConvertType(excelFile, rows);
                if (scriptBufferOffset != 1)
                {
                    excelFileTCv4.SetScriptCode(scriptBuffer);
                }

                if (isAffixes)
                {
                    excelFileTCv4.SetSecondaryStringsCollection(affixGroupsList);
                }

                byte[] convertedBytes = excelFileTCv4.ToByteArray();
                String writePath = Path.Combine(Config.HglDir, excelFile.FilePath);
                String backupPath = writePath + ".bak";

                if (File.Exists(backupPath)) File.Delete(backupPath);
                File.Move(writePath, backupPath);
                File.WriteAllBytes(writePath, convertedBytes);

                //int bp2 = 0;
            }

            //int bp1 = 0;
        }
Beispiel #5
0
        /// <summary>
        /// This function checks every row/col of every excel file, determining if it needs to be visible/public or not.
        /// Any element non-zero for all rows, needs to be public (or add new OutputAttribute for "const" values?)
        /// </summary>
        public static void ExcelValuesDeepScan()
        {
            FileManager fileManager = new FileManager(Config.HglDir);
            fileManager.ExtractAllExcel();

            Dictionary<uint, uint> rowTypeCounts = new Dictionary<uint, uint>();
            Dictionary<String, uint[]> outputMessages = new Dictionary<String, uint[]>();
            Dictionary<String, ObjectDelegator> objectDelegators = new Dictionary<String, ObjectDelegator>();
            foreach (PackFileEntry fileEntry in fileManager.FileEntries.Values)
            {
                if (!fileEntry.Name.EndsWith(ExcelFile.Extension)) continue;

                byte[] fileBytes = fileManager.GetFileBytes(fileEntry, true);
                Debug.Assert(fileBytes != null);

                ExcelFile excelFile = new ExcelFile(fileBytes, fileEntry.Path);
                if (excelFile.Attributes.IsEmpty) continue;

                Debug.WriteLine("Checking file: " + fileEntry.Path);

                uint structureId = excelFile.Attributes.StructureId;
                uint structureUseCount = 0;
                if (rowTypeCounts.TryGetValue(structureId, out structureUseCount))
                {
                    rowTypeCounts[structureId] = ++structureUseCount;
                }
                else
                {
                    rowTypeCounts.Add(structureId, 1);
                }

                ObjectDelegator excelDelegator;
                Type rowType = excelFile.Attributes.RowType;
                FieldInfo[] fieldInfos = rowType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                int rowCount = excelFile.Rows.Count;

                // create delegates
                if (!objectDelegators.TryGetValue(excelFile.StringId, out excelDelegator))
                {
                    excelDelegator = new ObjectDelegator(fieldInfos);
                    objectDelegators.Add(excelFile.StringId, excelDelegator);
                }

                // check by column, by row
                int col = -1;
                foreach (FieldInfo fieldInfo in fieldInfos)
                {
                    if (++col == 0) continue; // row header

                    ObjectDelegator.FieldGetValueDelegate getValue = excelDelegator.GetFieldGetDelegate(fieldInfo.Name);
                    ExcelFile.OutputAttribute outputAttribute = ExcelFile.GetExcelAttribute(fieldInfo);

                    bool isArray = false;
                    bool allEqual = true;
                    Object firstValue = null;
                    Array firstValueArray = null;
                    int arrayIndexFirstDifferent = -1;
                    int row = -1;
                    String message = null;
                    foreach (Object value in excelFile.Rows.Select(rowObject => getValue(rowObject)))
                    {
                        arrayIndexFirstDifferent = -1;
                        if (++row == 0)
                        {
                            if (fieldInfo.FieldType.BaseType == typeof(Array))
                            {
                                firstValueArray = (Array)value;
                                isArray = true;
                                IEnumerator enumerator = firstValueArray.GetEnumerator();
                                enumerator.MoveNext();
                                firstValue = enumerator.Current;
                            }
                            else
                            {
                                firstValue = value;
                            }
                            continue;
                        }

                        if (isArray)
                        {
                            Array objArray = (Array)value;
                            Debug.Assert(firstValueArray != null);

                            bool arrayEqual = true;
                            IEnumerator enumeratorFirst = firstValueArray.GetEnumerator();
                            IEnumerator enumeratorCurrent = objArray.GetEnumerator();
                            while (enumeratorFirst.MoveNext())
                            {
                                enumeratorCurrent.MoveNext();
                                arrayIndexFirstDifferent++;

                                Object objFirst = enumeratorFirst.Current;
                                Object objCurrent = enumeratorCurrent.Current;

                                if (firstValue == null) firstValue = objFirst;
                                if (objFirst.Equals(objCurrent)) continue;

                                arrayEqual = false;
                                break;
                            }

                            if (arrayEqual) continue;
                            allEqual = false;
                            break;
                        }

                        Debug.Assert(firstValue != null);
                        if (firstValue.Equals(value)) continue;
                        allEqual = false;
                        break;
                    }
                    Debug.Assert(firstValue != null);

                    Object constValue = null;
                    bool ignoreConstCheck = false;
                    if (outputAttribute != null)
                    {
                        constValue = outputAttribute.ConstantValue;
                        ignoreConstCheck = outputAttribute.DebugIgnoreConstantCheck;
                    }

                    if (fieldInfo.IsPrivate)
                    {
                        if (!allEqual)
                        {
                            message = String.Format("Warning: Private column (Type = {1}, StructureId = 0x{2}) \"{0}\" has per-row differing values",
                                fieldInfo.Name, fieldInfo.FieldType, structureId.ToString("X8")); // need to add structureId to ensure message is unique per structure type

                            if (isArray)
                            {
                                message += ", first index differing: " + arrayIndexFirstDifferent;
                            }
                        }
                        else // allEqual && IsPrivate
                        {
                            if (isArray)
                            {
                                if (fieldInfo.FieldType == typeof(Int32[]))
                                {
                                    if (firstValue.Equals((Int32)0)) continue;
                                }
                                else if (fieldInfo.FieldType == typeof(byte[]))
                                {
                                    if (firstValue.Equals((byte)0x00)) continue;
                                }
                                else
                                {
                                    Debug.Assert(false, "Unexpected Array Type: " + fieldInfo.FieldType);
                                }

                                if (outputAttribute != null && firstValue.Equals(outputAttribute.ConstantValue)) continue;

                                message = String.Format("Warning: Private column (Type = {2}, StructureId = 0x{3}) \"{0}\" has constant value not zero \"{1}\"",
                                    fieldInfo.Name, firstValue, fieldInfo.FieldType, structureId.ToString("X8"));
                            }
                            else // not array
                            {
                                if (firstValue.Equals(constValue)) continue;
                                if (fieldInfo.FieldType == typeof(Int32) &&
                                    ((Int32)firstValue == 0 && (firstValue.Equals(constValue) || constValue == null))) continue;
                                if (fieldInfo.FieldType == typeof(Int16) &&
                                    ((Int16)firstValue == 0 && (firstValue.Equals(constValue) || constValue == null))) continue;

                                message = String.Format("Warning: Private column (Type = {2}, StructureId = 0x{3}) \"{0}\" has constant value not zero \"{1}\"",
                                    fieldInfo.Name, firstValue, fieldInfo.FieldType, structureId.ToString("X8"));

                                if (outputAttribute != null && outputAttribute.ConstantValue != null) message += " (outputAttribute.ConstantValue is set)";
                            }
                        }
                    }
                    else // IsPublic
                    {
                        if (ignoreConstCheck) continue;

                        if (allEqual && fieldInfo.IsPublic && rowCount != 1 && (outputAttribute == null || outputAttribute.ConstantValue == null))
                        {
                            message = String.Format("Notice: Public column (Type = {2}, StructureId = 0x{3}) \"{0}\" has constant value \"{1}\"",
                                fieldInfo.Name, firstValue, fieldInfo.FieldType, structureId.ToString("X8"));
                        }
                    }

                    if (message == null) continue;

                    uint[] messageCounts;
                    if (outputMessages.TryGetValue(message, out messageCounts))
                    {
                        outputMessages[message] = new[] { messageCounts[0] + 1, structureId };
                    }
                    else
                    {
                        outputMessages.Add(message, new uint[] { 1, structureId });
                    }
                }

                //int bp3 = 0;
            }

            String previousStringId = null;
            StringWriter stringWriter = new StringWriter();
            foreach (KeyValuePair<String, uint[]> message in outputMessages)
            {
                String msg = message.Key;
                uint msgCount = message.Value[0];
                uint forStructureId = message.Value[1];
                uint structureCount = rowTypeCounts[forStructureId];

                if (structureCount != msgCount) continue; // if not equal, then we have a message in one table, but in another table it's not applicable

                String[] stringIds1 = (from dataTableAttribute in DataFile.DataFileMap
                                       where dataTableAttribute.Value.StructureId == forStructureId
                                       select dataTableAttribute.Key).ToArray();
                String[] stringIds2 = (from dataTableAttribute in DataFile.DataFileMapTestCenter
                                       where dataTableAttribute.Value.StructureId == forStructureId
                                       select dataTableAttribute.Key).ToArray();
                String[] stringIds3 = (from dataTableAttribute in DataFile.DataFileMapResurrection
                                       where dataTableAttribute.Value.StructureId == forStructureId
                                       select dataTableAttribute.Key).ToArray();
                String[] stringIds4 = (from dataTableAttribute in DataFile.DataFileMapMod
                                       where dataTableAttribute.Value.StructureId == forStructureId
                                       select dataTableAttribute.Key).ToArray();
                String stringIdPrepend = String.Join(",", stringIds1) + String.Join(",", stringIds2) + String.Join(",", stringIds3) + String.Join(",", stringIds4);

                if (previousStringId != stringIdPrepend)
                {
                    //Console.WriteLine(stringIdPrepend);
                    stringWriter.WriteLine(stringIdPrepend);
                    previousStringId = stringIdPrepend;
                }

                //Console.WriteLine(msg);
                stringWriter.WriteLine(msg);
            }
            File.WriteAllText(@"C:\asdf.txt", stringWriter.ToString());
        }
Beispiel #6
0
        private DataTable _LoadExcelTable(ExcelFile excelFile, bool doRelations, bool force)
        {
            String tableName = excelFile.StringId;
            DataTable dataTable = XlsDataSet.Tables[tableName];
            if (dataTable != null && !force) return dataTable;
            if (dataTable != null)
            {
                XlsDataSet.Relations.Clear();
                XlsDataSet.Tables.Remove(tableName);
            }
            dataTable = XlsDataSet.Tables.Add(tableName);
            dataTable.TableName = tableName;
            dataTable.ExtendedProperties.Add("FileHeader", excelFile._excelFileHeader.DeepClone());

            Type dataType = excelFile.Attributes.RowType;
            List<OutputAttribute> outputAttributes = new List<OutputAttribute>();

            #region Generate Columns
            DataColumn indexColumn = dataTable.Columns.Add("Index");
            indexColumn.AutoIncrement = true;
            indexColumn.Unique = true;
            dataTable.PrimaryKey = new[] { indexColumn };
            outputAttributes.Add(null);

            FieldInfo[] fieldInfos = dataType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            foreach (FieldInfo fieldInfo in fieldInfos)
            {
                OutputAttribute excelAttribute = ExcelFile.GetExcelAttribute(fieldInfo);

                // The only private field we add is the TableHeader
                if (fieldInfo.IsPrivate)
                {
                    if (fieldInfo.FieldType != typeof(ExcelFile.RowHeader)) continue;

                    outputAttributes.Add(null);
                    dataTable.Columns.Add(fieldInfo.Name, typeof(String));
                    continue;
                }

                Type fieldType = fieldInfo.FieldType;
                bool isArray = false;
                bool isEnum = false;
                if (fieldInfo.FieldType.BaseType == typeof(Array))
                {
                    fieldType = typeof(String);
                    isArray = true;
                }
                else if (fieldInfo.FieldType.BaseType == typeof(Enum) && excelAttribute == null)
                {
                    fieldType = fieldInfo.FieldType;
                    isEnum = true;
                }

                DataColumn dataColumn = dataTable.Columns.Add(fieldInfo.Name, fieldType);
                if (isArray)
                {
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsArray, true);
                }
                else if (isEnum)
                {
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsEnum, true);
                }

                if (excelAttribute == null)
                {
                    outputAttributes.Add(null);
                    continue;
                }

                outputAttributes.Add(excelAttribute);

                if (excelAttribute.IsStringOffset)
                {
                    dataColumn.DataType = typeof(String);
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsStringOffset, true);
                    dataColumn.DefaultValue = String.Empty;
                }

                if (excelAttribute.IsScript)
                {
                    dataColumn.DataType = typeof(String);
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsScript, true);
                    dataColumn.DefaultValue = String.Empty;
                }

                if (excelAttribute.IsSecondaryString)
                {
                    dataColumn.DataType = typeof(String);
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsSecondaryString, true);
                    dataColumn.DefaultValue = String.Empty;
                }

                if (excelAttribute.IsStringIndex)
                {
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsStringIndex, true);

                    // Add new column for the string
                    DataColumn dataColumnString = dataTable.Columns.Add(fieldInfo.Name + "_string", typeof(String));
                    dataColumnString.DefaultValue = String.Empty;
                    outputAttributes.Add(null);
                    dataColumnString.ExtendedProperties.Add(ColumnKeys.IsRelationGenerated, true);
                }

                if (excelAttribute.IsTableIndex)
                {
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsTableIndex, true);

                    // Add new column for the string
                    DataColumn dataColumnString = dataTable.Columns.Add(fieldInfo.Name + "_string", typeof(String));
                    dataColumnString.DefaultValue = String.Empty;
                    outputAttributes.Add(null);
                    dataColumnString.ExtendedProperties.Add(ColumnKeys.IsRelationGenerated, true);
                }

                if (excelAttribute.IsBitmask)
                {
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsBitmask, true);
                }

                if (excelAttribute.IsBool)
                {
                    dataColumn.ExtendedProperties.Add(ColumnKeys.IsBool, true);
                }
            }

            if (excelFile.Attributes.HasStats) // items, missiles, monsters, objects, players
            {
                DataColumn extendedDataColumn = dataTable.Columns.Add("Stats");
                extendedDataColumn.DataType = typeof(String);
                extendedDataColumn.ExtendedProperties.Add(ExcelFile.ColumnTypeKeys.IsStats, true);
                outputAttributes.Add(null);
            }
            #endregion

            #region Generate Rows
            int row = 1;
            object[] baseRow = new object[outputAttributes.Count];
            ObjectDelegator objectDelegator = new ObjectDelegator(fieldInfos);
            foreach (Object tableRow in excelFile.Rows)
            {
                int col = 1;
                foreach (FieldInfo fieldInfo in fieldInfos)
                {
                    Object value = objectDelegator[fieldInfo.Name](tableRow);

                    if (fieldInfo.IsPrivate)
                    {
                        if (fieldInfo.FieldType != typeof(ExcelFile.RowHeader)) continue;
                        baseRow[col++] = FileTools.ObjectToStringGeneric(value, ",");
                        continue;
                    }

                    OutputAttribute excelOutputAttribute = outputAttributes[col];

                    if (excelOutputAttribute == null)
                    {
                        if (value.GetType().BaseType == typeof(Array))
                        {
                            value = ((Array)value).ToString(",");
                        }

                        baseRow[col++] = value;
                        continue;
                    }

                    if (excelOutputAttribute.IsStringOffset)
                    {
                        int valueInt = (int)value;
                        baseRow[col++] = (valueInt != -1) ? excelFile.ReadStringTable(valueInt) : String.Empty;
                        continue;
                    }

                    if (excelOutputAttribute.IsSecondaryString)
                    {
                        int valueInt = (int)value;
                        baseRow[col++] = (valueInt != -1) ? excelFile.ReadSecondaryStringTable(valueInt) : String.Empty;
                        continue;
                    }

                    if (excelOutputAttribute.IsScript)
                    {
                        int scriptOffset = (int)value;
                        if (scriptOffset == 0)
                        {
                            baseRow[col++] = String.Empty;
                            continue;
                        }

                        String script;
                        if (scriptOffset == 9649 && excelFile.StringId == "SKILLS") // todo: not sure what's with this script...
                        {
                            /* Compiled Bytes:
                             * 26,30,700,6,26,1,399,358,669,616562688,711,26,62,3,17,669,641728512,26,8,711,26,62,3,17,358,669,322961408,26,5,700,6,26,1,399,358,388,0
                             *
                             * Ending Stack (FIFO):
                             * SetStat669('sfx_attack_pct', 'all', 30 * ($sklvl - 1))
                             * SetStat669('sfx_duration_pct', 'all', get_skill_level(@unit, 'Shield_Mastery'))
                             * SetStat669('damage_percent_skill', 8 * get_skill_level(@unit, 'Shield_Mastery'))
                             * SetStat669('damage_percent_skill', 8 * get_skill_level(@unit, 'Shield_Mastery')) + 5 * ($sklvl - 1)
                             *
                             * The last SetStat has strange overhang - decompiling wrong?
                             * Or is it "supposed" to be there?
                             * i.e. It's actually decompiling correctly, but because I've assumed such scripts to be wrong (as the end +5... segment is useless) we get the Stack exception
                             */
                            int[] scriptCode = excelFile.ReadScriptTable(scriptOffset);
                            script = scriptCode != null ? FileTools.ArrayToStringGeneric(scriptCode, ",") : "ScriptError";
                            baseRow[col++] = script;
                            continue;
                        }

                        //if (fieldInfo.Name == "props1" && row == 45)
                        //{
                        //    int bp = 0;
                        //}

                        ExcelScript excelScript = new ExcelScript(this);

                        try
                        {
                            if (ExcelScript.DebugEnabled)
                            {
                                int[] scriptCode = excelFile.ReadScriptTable(scriptOffset);
                                script = scriptCode != null ? FileTools.ArrayToStringGeneric(scriptCode, ",") : String.Empty;

                                script = excelScript.Decompile(excelFile.ScriptBuffer, scriptOffset, script, excelFile.StringId, row, col, fieldInfo.Name);
                            }
                            else
                            {
                                script = excelScript.Decompile(excelFile.ScriptBuffer, scriptOffset);
                            }

                            //if (script.StartsWith("GetStat666('skill_points_bonus_total', '') > -1;"))
                            //{
                            //    int bp = 0;
                            //}
                        }
                        catch (Exception)
                        {
                            int[] scriptCode = excelFile.ReadScriptTable(scriptOffset);
                            script = scriptCode != null ? FileTools.ArrayToStringGeneric(scriptCode, ",") : "ScriptError";
                        }

                        baseRow[col++] = script;
                        continue;
                    }

                    if (excelOutputAttribute.IsTableIndex || excelOutputAttribute.IsStringIndex)
                    {
                        if (value.GetType().BaseType == typeof(Array))
                        {
                            value = ((Array)value).ToString(",");
                        }
                        else
                        {
                            value = (int)value;
                        }

                        baseRow[col++] = value;
                        col++; // for _strings relational column
                        continue;
                    }

                    // Else its something else, ie bitmask, bool, table/string index
                    baseRow[col++] = value;
                }

                // stats, only a component of the UnitData row type
                if (excelFile.Attributes.HasStats)
                {
                    baseRow[col++] = FileTools.ArrayToStringGeneric(excelFile.ReadStats(row - 1), ",");
                }

                dataTable.Rows.Add(baseRow);
                row++;
            }

            #endregion

            // Generate Relationships as required
            if (doRelations) _GenerateRelations(excelFile);

            return dataTable;
        }
Beispiel #7
0
        /// <summary>
        /// Initialise private variables and generate excel script functions if required.
        /// </summary>
        public ExcelScript(FileManager fileManager)
        {
            if (fileManager == null) throw new ArgumentNullException("fileManager", "File Manager cannot be null.");
            if (!fileManager.DataFiles.ContainsKey("STATS")) throw new Exceptions.ScriptNotInitialisedException("The supplied file manager did not have a valid Stats table.");

            // these initial counts are required for script compiling when determing if a function is from the .exe or from an Excel table
            if (!_haveExcelFunctions)
            {
                _initCallFunctionsCountSinglePlayer = CallFunctionsSinglePlayer.Count;
                _initCallFunctionsTestCenterCount = CallFunctionsTestCenter.Count;
                _initCallFunctionsResurrectionCount = CallFunctionsResurrection.Count;
            }

            _fileManager = fileManager;
            if (_fileManager.IsVersionResurrection || _fileManager.IsVersionMod)
            {
                CallFunctions = CallFunctionsResurrection;
                _initCallFunctionsCount = _initCallFunctionsResurrectionCount;
                _debugRoot = DebugRootResurrection;
            }
            else if (_fileManager.IsVersionTestCenter)
            {
                CallFunctions = CallFunctionsTestCenter;
                _initCallFunctionsCount = _initCallFunctionsTestCenterCount;
                _debugRoot = DebugRootTestCenter;
            }
            else
            {
                CallFunctions = CallFunctionsSinglePlayer;
                _initCallFunctionsCount = _initCallFunctionsCountSinglePlayer;
                _debugRoot = DebugRoot;
            }

            _statsTable = (ExcelFile)_fileManager.DataFiles["STATS"];
            _statsDelegator = _fileManager.DataFileDelegators["STATS"];
            if (_globalDebug) EnableDebug(true);

            if (CallFunctions.Count == _initCallFunctionsCount) _GenerateExcelScriptFunctions();
        }
Beispiel #8
0
        public byte[] ExportSQL(FileManager fileManager, string tablePrefix = "")
        {
            string[] sqlReserved = new string[] { "group", "condition", "left", "right", "default", "key", "force", "analyze", "kill", "usage", "order" };

            StringWriter stringWriter = new StringWriter();
            string tableName = String.Format("{0}{1}", tablePrefix, StringId.ToLower());

            stringWriter.WriteLine(String.Format("CREATE TABLE {0} (", tableName));
            stringWriter.WriteLine("\tid INT NOT NULL PRIMARY KEY,");

            String columnDec = "\t{0} {1}{2}";

            int colCount = 1;

            ObjectDelegator objectDelegator;
            if (fileManager == null || !fileManager.DataFileDelegators.ContainsKey(StringId))
            {
                objectDelegator = new ObjectDelegator(Attributes.RowType.GetFields());

                FieldInfo headerField = DataType.GetField("header", BindingFlags.Instance | BindingFlags.NonPublic);
                objectDelegator.AddField(headerField);
            }
            else
            {
                objectDelegator = fileManager.DataFileDelegators[StringId];
            }

            int noColumns = objectDelegator.FieldCount - 1; // remove header

            foreach (ObjectDelegator.FieldDelegate field in objectDelegator)
            {
                if (field.Name == "header") continue; // dont want this

                String columnName = field.Name;
                String dataType = String.Empty;
                String formatted = String.Empty;

                if (sqlReserved.Where(str => str == columnName.ToLower()).Any() == true)
                {
                    columnName = "a" + columnName;
                }

                // Special types
                OutputAttribute excelOutput = GetExcelAttribute(field.Info);
                if (excelOutput != null)
                {
                    if (excelOutput.IsScript || excelOutput.IsSecondaryString || excelOutput.IsStringOffset) dataType = "TEXT";
                    else if (excelOutput.IsBitmask) dataType = "BIGINT";
                }

                if (dataType == String.Empty)
                {
                    if (field.FieldType == typeof(int)) dataType = "INT";
                    else if (field.FieldType == typeof(float)) dataType = "DECIMAL";
                    else if (field.FieldType == typeof(byte)) dataType = "TINYINT";
                    else if (field.FieldType == typeof(short)) dataType = "SMALLINT";
                    else if (field.FieldType == typeof(uint) || field.FieldType == typeof(Int64)) dataType = "BIGINT";
                    else if (field.FieldType == typeof(string))
                    {
                        MarshalAsAttribute marshalAs = (MarshalAsAttribute)field.Info.GetCustomAttributes(typeof(MarshalAsAttribute), false).First();
                        dataType = String.Format("VARCHAR({0})", marshalAs.SizeConst);
                    }
                    else if (field.FieldType.BaseType == typeof(Array)) { dataType = "TEXT"; }
                }

                formatted = String.Format(columnDec, columnName, dataType, colCount < noColumns ? "," : String.Empty);
                stringWriter.WriteLine(formatted);
                colCount++;
            }

            stringWriter.WriteLine(");");
            stringWriter.WriteLine("INSERT INTO {0}", tableName);
            stringWriter.WriteLine("VALUES");

            colCount = 1;
            int rowCount = 0;
            int noRows = Rows.Count;
            StringWriter valueString = new StringWriter();

            foreach (Object rowObject in Rows)
            {
                valueString.Write(String.Format("\t({0},", rowCount)); // write the id

                foreach (ObjectDelegator.FieldDelegate field in objectDelegator)
                {
                    if (field.Name == "header") continue; // dont want this

                    OutputAttribute excelOutput = GetExcelAttribute(field.Info);
                    Object objValue = field.GetValue(rowObject);
                    bool valueParsed = false;

                    if (excelOutput != null)
                    {
                        if (excelOutput.IsScript)
                        {
                            int[] scriptTable = ReadScriptTable((int)objValue);
                            if (scriptTable != null)
                            {
                                int offset = (int)objValue;
                                int[] scriptbuffer = ReadScriptTable(offset);

                                String scriptString = FileTools.ArrayToStringGeneric(scriptbuffer, ",");
                                try
                                {
                                    if (fileManager != null)
                                    {
                                        ExcelScript excelScript = new ExcelScript(fileManager);
                                        scriptString = excelScript.Decompile(_scriptBuffer, offset);
                                        scriptString = StringToSQLString(scriptString);
                                        scriptString = EncapsulateString(scriptString);
                                        valueString.Write(scriptString);
                                    }
                                    else
                                    {
                                        valueString.Write(scriptString);
                                    }
                                }
                                catch (Exception e)
                                {
                                    valueString.Write(EncapsulateString(scriptString));
                                    Debug.WriteLine(e.ToString());
                                    scriptString = "ScriptError(" + scriptString + ")";
                                }
                            }
                            else
                            {
                                valueString.Write("\"\"");
                            }
                            valueParsed = true;
                        }
                        else if (excelOutput.IsSecondaryString)
                        {
                            if ((int)objValue != -1)
                            {
                                string secString = ReadSecondaryStringTable((int)objValue);
                                valueString.Write(String.Format("\"{0}\"", secString));
                            }
                            else
                            {
                                valueString.Write("\"\"");
                            }
                            valueParsed = true;
                        }
                        else if (excelOutput.IsStringOffset)
                        {
                            string offString = ReadStringTable((int)objValue);
                            offString = StringToSQLString(offString);
                            offString = String.Format("\"{0}\"", offString);

                            valueString.Write(offString);
                            valueParsed = true;
                        }
                        else if (excelOutput.IsBitmask)
                        {
                            valueString.Write((uint)objValue);
                            valueParsed = true;
                        }
                    }

                    if (valueParsed == false)
                    {
                        if (field.FieldType == typeof(string))
                        {
                            string strValue = EncapsulateString(StringToSQLString((objValue.ToString())));
                            valueString.Write(strValue);
                        }
                        else if (field.FieldType.BaseType == typeof(Array))
                        {
                            string strValue = EncapsulateString(((Array)objValue).ToString(","));
                            valueString.Write(strValue);
                        }
                        else if (field.FieldType == typeof(float))
                        {
                            string strValue = ((float)objValue).ToString("r");
                            valueString.Write(strValue);
                        }
                        else
                        {
                            valueString.Write(objValue);
                        }
                    }

                    if (colCount < noColumns) valueString.Write(",");
                    else valueString.Write(")");
                    colCount++;
                }
                if (rowCount < noRows - 1) valueString.WriteLine(",");
                else valueString.WriteLine(";");
                rowCount++;
                colCount = 1;
            }

            stringWriter.Write(valueString.ToString());

            byte[] buffer = FileTools.StringToASCIIByteArray(stringWriter.ToString());
            return buffer;
        }
Beispiel #9
0
        public ExcelFile(String filePath, FileManager.ClientVersions clientVersion = FileManager.ClientVersions.SinglePlayer)
        {
            Thread.CurrentThread.CurrentCulture = Common.EnglishUSCulture;

            IsExcelFile = true;
            FilePath = filePath;
            StringId = _GetStringId(filePath);
            if (StringId == null) throw new Exceptions.DataFileStringIdNotFound(filePath);

            // get the excel type attributes
            DataFileAttributes dataFileAttributes = null;
            if (clientVersion == FileManager.ClientVersions.Mod)
            {
                DataFileMapMod.TryGetValue(StringId, out dataFileAttributes);
            }
            if (dataFileAttributes == null && (clientVersion == FileManager.ClientVersions.Resurrection || clientVersion == FileManager.ClientVersions.Mod))
            {
                DataFileMapResurrection.TryGetValue(StringId, out dataFileAttributes);
            }
            if (dataFileAttributes == null && clientVersion == FileManager.ClientVersions.TestCenter)
            {
                DataFileMapTestCenter.TryGetValue(StringId, out dataFileAttributes);
            }
            if (dataFileAttributes == null)
            {
                DataFileMap.TryGetValue(StringId, out dataFileAttributes);
            }
            Attributes = dataFileAttributes;

            if (Attributes == null) return;

            // create field delegators
            if (Attributes.RowType != null)
            {
                FieldInfo[] dataFileFields = Attributes.RowType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                dataFileFields = dataFileFields.OrderBy(f => f.MetadataToken).ToArray(); // order by defined order - GetFields does not guarantee ordering
                Delegator = new ObjectDelegator(dataFileFields);
            }
            else
            {
                Debug.WriteLine("Warning: Excel Definition has no RowType defined: " + StringId);
            }

            // if we're empty, then just return
            if (Attributes.IsEmpty)
            {
                HasIntegrity = true;
                Rows = new List<Object>();
                return;
            }

            // we're using hard-coded mysh script table for SKILLS
            if (StringId == "SKILLS") _myshBuffer = Skills.Mysh.Data;

            // we aren't parsing file data, so need to manually assign a structure id
            _excelFileHeader.StructureID = Attributes.StructureId;
        }
Beispiel #10
0
        public byte[] ExportCSV(FileManager fileManager, IEnumerable<String> columnNames = null)
        {
            if (Attributes.IsEmpty) return new byte[0];

            //// init stuffs
            byte[] csvBuffer = new byte[1024];
            int csvOffset = 0;
            bool isProperties = (StringId == "PROPERTIES" || StringId == "_TCv4_PROPERTIES");

            ObjectDelegator objectDelegator;
            if (fileManager == null || !fileManager.DataFileDelegators.ContainsKey(StringId))
            {
                objectDelegator = new ObjectDelegator(Attributes.RowType.GetFields());

                FieldInfo headerField = DataType.GetField("header", BindingFlags.Instance | BindingFlags.NonPublic);
                objectDelegator.AddField(headerField);
            }
            else
            {
                objectDelegator = fileManager.DataFileDelegators[StringId];
            }

            //// header row
            // tables can have different header values
            String tableHeaderStr = String.Format("{0}({1})", StringId, FileTools.ObjectToStringGeneric(_excelFileHeader, ","));

            // rest of columns
            List<String> columnsList = new List<String> { tableHeaderStr };
            foreach (ObjectDelegator.FieldDelegate fieldDelegate in objectDelegator)
            {
                if (columnNames == null)
                {
                    if (!fieldDelegate.IsPublic) continue;
                }
                else if (!columnNames.Contains(fieldDelegate.Name))
                {
                    continue;
                }

                columnsList.Add(fieldDelegate.Name);
            }

            // excel table type-specific columns
            if (Attributes.HasStats) columnsList.Add("Stats");
            if (isProperties) columnsList.Add("Script");

            // column header row
            String[] columns = columnsList.ToArray();
            int colCount = columns.Length;
            int rowCount = Count + 1; // +1 for column headers

            //// csv generation
            String[][] strings = new string[rowCount][];
            strings[0] = columns;
            int col = -1;
            foreach (ObjectDelegator.FieldDelegate fieldDelegate in objectDelegator)
            {
                if (!columns.Contains(fieldDelegate.Name) && fieldDelegate.Name != "header") continue;

                col++;
                OutputAttribute excelAttribute = GetExcelAttribute(fieldDelegate.Info);

                //if (fieldDelegate.Name == "spawnFromMonsterUnitType")
                //{
                //    int bp = 0;
                //}

                int row = 0;
                foreach (Object rowObject in Rows)
                {
                    String[] rowStr = strings[++row];
                    if (rowStr == null)
                    {
                        rowStr = new String[colCount];
                        strings[row] = rowStr;
                    }

                    if (fieldDelegate.Name == "header")
                    {
                        RowHeader rowHeader = (RowHeader)fieldDelegate.GetValue(rowObject);
                        rowStr[col] = FileTools.ObjectToStringGeneric(rowHeader, ",");
                        continue;
                    }

                    if (fieldDelegate.Name == "code")
                    {
                        int code;
                        if (fieldDelegate.FieldType == typeof(short))
                        {
                            code = (int)(short)fieldDelegate.GetValue(rowObject); // yes, that extra (int) is *needed* to cast the short correctly
                        }
                        else
                        {
                            code = (int)fieldDelegate.GetValue(rowObject);
                        }

                        if (StringId == "REGION") // can't export region code values as chars due to weird chars
                        {
                            rowStr[col] = "\"" + code + "\"";
                        }
                        else
                        {
                            rowStr[col] = "\"" + _CodeToString(code) + "\"";
                        }

                        continue;
                    }

                    bool isArray = (fieldDelegate.FieldType.BaseType == typeof(Array));
                    if (excelAttribute != null)
                    {
                        if (excelAttribute.IsTableIndex && fileManager != null)
                        {
                            int[] indexValues;
                            Object indexObj = fieldDelegate.GetValue(rowObject);
                            if (isArray)
                            {
                                indexValues = (int[])indexObj;
                            }
                            else
                            {
                                indexValues = new[] { (int)indexObj };
                            }

                            String[] indexStrs = new String[indexValues.Length];
                            for (int i = 0; i < indexStrs.Length; i++)
                            {
                                if (indexValues[i] == -1) // empty string/no code
                                {
                                    indexStrs[i] = "-1";
                                    continue;
                                }

                                String tableStringId = excelAttribute.TableStringId;
                                String negative = String.Empty;
                                if (indexValues[i] < 0)
                                {
                                    indexValues[i] *= -1;
                                    negative = "-";
                                }

                                String indexStr = null;
                                if (fileManager.DataTableHasColumn(tableStringId, "code"))
                                {
                                    int code = fileManager.GetExcelIntFromStringId(tableStringId, indexValues[i], "code");
                                    if (code != 0) indexStr = _CodeToString(code);
                                }
                                else if (fileManager.DataTableHasColumn(tableStringId, "name"))
                                {
                                    indexStr = fileManager.GetExcelStringFromStringId(tableStringId, indexValues[i], "name");
                                }

                                if (indexStr == null)
                                {
                                    indexStr = fileManager.GetExcelStringFromStringId(tableStringId, indexValues[i]);
                                }

                                indexStrs[i] = negative + indexStr;
                            }

                            rowStr[col] = "\"" + String.Join(",", indexStrs) + "\"";
                            continue;
                        }

                        if (excelAttribute.IsStringOffset)
                        {
                            int offset = (int)fieldDelegate.GetValue(rowObject);
                            if (offset != -1)
                            {
                                rowStr[col] = ReadStringTable(offset);
                            }
                            continue;
                        }

                        if (excelAttribute.IsScript)
                        {
                            int offset = (int)fieldDelegate.GetValue(rowObject);
                            if ((offset == 0))
                            {
                                FileTools.WriteToBuffer(ref csvBuffer, ref csvOffset, FileTools.StringToASCIIByteArray("0"));
                                continue;
                            }
                            int[] buffer = ReadScriptTable(offset);
                            if (buffer == null) throw new Exceptions.ScriptFormatException("The script bytes were unable to be read using ReadScriptTable.", offset);

                            String scriptString = FileTools.ArrayToStringGeneric(buffer, ",");
                            if (fileManager != null)
                            {
                                if (offset == 9325 /*from DataTable export*/ || offset == 9649 /*from Object export*/ && StringId == "SKILLS") // todo: not sure what's with this script...
                                {
                                    /* Compiled Bytes:
                                     * 26,30,700,6,26,1,399,358,669,616562688,711,26,62,3,17,669,641728512,26,8,711,26,62,3,17,358,669,322961408,26,5,700,6,26,1,399,358,388,0
                                     *
                                     * Ending Stack (FIFO):
                                     * SetStat669('sfx_attack_pct', 'all', 30 * ($sklvl - 1))
                                     * SetStat669('sfx_duration_pct', 'all', get_skill_level(@unit, 'Shield_Mastery'))
                                     * SetStat669('damage_percent_skill', 8 * get_skill_level(@unit, 'Shield_Mastery'))
                                     * SetStat669('damage_percent_skill', 8 * get_skill_level(@unit, 'Shield_Mastery')) + 5 * ($sklvl - 1)
                                     *
                                     * The last SetStat has strange overhang - decompiling wrong?
                                     * Or is it "supposed" to be there?
                                     * i.e. It's actually decompiling correctly, but because I've assumed such scripts to be wrong (as the end +5... segment is useless) we get the Stack exception
                                     */

                                    scriptString = "ScriptError(" + scriptString + ")";
                                }
                                else
                                {
                                    try
                                    {
                                        ExcelScript excelScript = new ExcelScript(fileManager);
                                        scriptString = "\"" + excelScript.Decompile(_scriptBuffer, offset, scriptString, StringId, row, col, fieldDelegate.Name) + "\"";
                                    }
                                    catch (Exception e)
                                    {
                                        Debug.WriteLine(e.ToString());
                                        scriptString = "ScriptError(" + scriptString + ")";
                                    }
                                }
                            }

                            rowStr[col] = scriptString;
                            continue;
                        }

                        if (excelAttribute.IsSecondaryString)
                        {
                            int index = (int)fieldDelegate.GetValue(rowObject);
                            if (index != -1)
                            {
                                rowStr[col] = SecondaryStrings[index];
                            }
                            continue;
                        }

                        if (excelAttribute.IsBitmask)
                        {
                            rowStr[col] = "\"" + fieldDelegate.GetValue(rowObject) + "\"";
                            continue;
                        }
                    }

                    Object outValue = fieldDelegate.GetValue(rowObject);
                    if (isArray)
                    {
                        rowStr[col] = ((Array)outValue).ToString(",");
                    }
                    else if (fieldDelegate.FieldType == typeof(float))
                    {
                        rowStr[col] = ((float)outValue).ToString("r");
                    }
                    //else if (fieldDelegate.FieldType.BaseType == typeof(Enum)) // might as well export enums as their string representations
                    //{
                    //    rowStr[col] = ((UInt32)outValue).ToString();
                    //}
                    else
                    {
                        rowStr[col] = outValue.ToString();
                    }
                }
            }

            // stats
            if (Attributes.HasStats)
            {
                col++;
                int row = -1;
                foreach (String[] rowStr in strings)
                {
                    if (row == -1) // columns header row
                    {
                        row++;
                        continue;
                    }

                    rowStr[col] = StatsBuffer[row++].ToString(",");
                }
            }

            // properties scripts
            if (isProperties)
            {
                // not point in doing this
                //if (tableHeader.Unknown1 != 2 || scriptRow == ExcelFunctions.Count - 1) // need 1 extra row for some reason

                col++;
                int row = -1;
                foreach (String[] rowStr in strings)
                {
                    if (row == -1)
                    {
                        row++;
                        continue;
                    }

                    if (row >= ExcelFunctions.Count) break;

                    ExcelFunction excelScript = ExcelFunctions[row++];
                    String excelScriptFunction = String.Empty;
                    foreach (ExcelFunction.Parameter paramater in excelScript.Parameters)
                    {
                        excelScriptFunction += String.Format("\n{0},{1},{2},{3}", paramater.Name, paramater.Unknown, paramater.TypeId, paramater.TypeValues.ToString(","));
                    }

                    if (excelScript.ScriptByteCode != null)
                    {
                        int offset = 0;
                        excelScriptFunction += "\n" + FileTools.ByteArrayToInt32Array(excelScript.ScriptByteCode, ref offset, excelScript.ScriptByteCode.Length / 4).ToString(",") + "\n";
                    }

                    rowStr[col] = excelScriptFunction;
                }
            }

            //// join string arrays and create byte array
            String[] rows = new String[rowCount];
            col = 0;
            foreach (String[] rowStr in strings)
            {
                rows[col] = String.Join("\t", rowStr);
                col++;
            }

            String csvString = String.Join(Environment.NewLine, rows);
            return csvString.ToASCIIByteArray();
        }
Beispiel #11
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;
        }
Beispiel #12
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;
        }