Esempio n. 1
0
        /// <summary>
        /// cf. GeneralGFF.fileclick_Create()
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contextclick_AddTopLevelStruct(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type = FieldTypes.Struct;

            if (_f.GffData != null)
            {
                field.label = Path.GetFileNameWithoutExtension(_f.GffData.Pfe).ToUpper();
            }
            else
            {
                _f.GffData         = new GffData();         // init GffData! ->
                _f.GffData.TypeVer = "GFF V3.2";
                _f.GffData.Type    = GffType.generic;

                field.label = Globals.TopLevelStruct;
            }

            field.Struct        = new Struct();
            field.Struct.typeid = UInt32.MaxValue;

            Nodes.Add(field.label);

            SelectedNode = Nodes[0];
        }
Esempio n. 2
0
        void contextclick_AddInt64(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type  = FieldTypes.INT64;
            field.label = GetUniqueLabel();
            field.INT64 = 0;

            AddField(field);
        }
Esempio n. 3
0
        void contextclick_AddFloat(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type  = FieldTypes.FLOAT;
            field.label = GetUniqueLabel();
            field.FLOAT = 0;

            AddField(field);
        }
Esempio n. 4
0
        void contextclick_AddDouble(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type   = FieldTypes.DOUBLE;
            field.label  = GetUniqueLabel();
            field.DOUBLE = 0;

            AddField(field);
        }
Esempio n. 5
0
        void contextclick_AddCExoString(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type       = FieldTypes.CExoString;
            field.label      = GetUniqueLabel();
            field.CExoString = String.Empty;

            AddField(field);
        }
Esempio n. 6
0
        void contextclick_AddCExoLocString(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type          = FieldTypes.CExoLocString;
            field.label         = GetUniqueLabel();
            field.CExoLocStrref = UInt32.MaxValue;

            AddField(field);
        }
Esempio n. 7
0
        void contextclick_AddVoid(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type  = FieldTypes.VOID;
            field.label = GetUniqueLabel();
            field.VOID  = new byte[0];

            AddField(field);
        }
Esempio n. 8
0
        void contextclick_AddList(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type  = FieldTypes.List;
            field.label = GetUniqueLabel();
//			field.List = new List<uint>();

            AddField(field);
        }
Esempio n. 9
0
        void contextclick_AddChar(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type  = FieldTypes.CHAR;
            field.label = GetUniqueLabel();
            field.CHAR  = 0;

            AddField(field);
        }
Esempio n. 10
0
        void contextclick_AddDword(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type  = FieldTypes.DWORD;
            field.label = GetUniqueLabel();
            field.DWORD = 0;

            AddField(field);
        }
Esempio n. 11
0
        /// <summary>
        /// Adds a field to the TreeList and selects it.
        /// </summary>
        /// <param name="field"></param>
        /// <param name="locale"></param>
        void AddField(GffData.Field field, GffData.Locale locale = null)
        {
            string text = GeneralGFF.ConstructNodetext(field, locale);
            var    node = new Sortable(text, field.label);

            node.Tag = field;
            SelectedNode.Nodes.Add(node);

            SelectedNode = node;

            _f.GffData.Changed = true;
            _f.GffData         = _f.GffData;
        }
Esempio n. 12
0
        /// <summary>
        /// Adds a Struct (a Feat structure) to the "FeatList" List.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contextclick_AddFeat(object sender, EventArgs e)
        {
            BeginUpdate();

            TreeNode top = TopNode;

            var field = new GffData.Field();

            field.type          = FieldTypes.Struct;
            field.label         = SelectedNode.Nodes.Count.ToString(); // Structs in Lists do not have a Label
            field.Struct        = new Struct();
            field.Struct.typeid = 1;                                   // <- that's what's in the UTCs I've looked at.

            string text = GeneralGFF.ConstructNodetext(field);
            var    node = new Sortable(text, field.label);

            node.Tag = field;
            int id = SelectedNode.Nodes.Add(node);


            field       = new GffData.Field();
            field.type  = FieldTypes.WORD;
            field.label = "Feat";
            field.WORD  = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            SelectedNode = SelectedNode.Nodes[id];
            SelectedNode.Expand();

            TopNode = top;

            _f.GffData.Changed = true;
            _f.GffData         = _f.GffData;

            EndUpdate();

            node.EnsureVisible();             // yes those calls are in a specific sequence.
        }
Esempio n. 13
0
        void contextclick_AddStruct(object sender, EventArgs e)
        {
            var field = new GffData.Field();

            field.type = FieldTypes.Struct;

            if (SelectedNode.Tag != null &&
                ((GffData.Field)SelectedNode.Tag).type == FieldTypes.List)
            {
                field.label = SelectedNode.Nodes.Count.ToString();
            }
            else
            {
                field.label = GetUniqueLabel();
            }

            field.Struct        = new Struct();
            field.Struct.typeid = 0;

            AddField(field);
        }
Esempio n. 14
0
        /// <summary>
        /// Adds the three Structs of a tint to a specified node.
        /// </summary>
        /// <param name="node"></param>
        void AddTints(TreeNode node)
        {
            GffData.Field field;
            Sortable      part, val;

            for (int i = 1; i != 4; ++i)
            {
                field               = new GffData.Field();
                field.type          = FieldTypes.Struct;
                field.label         = i.ToString();
                field.Struct        = new Struct();
                field.Struct.typeid = 0;                 // <- that's what's in the UTCs I've looked at.

                string text = GeneralGFF.ConstructNodetext(field);
                part     = new Sortable(text, field.label);
                part.Tag = field;
                node.Nodes.Add(part);


                var colors = new List <string>()
                {
                    "a", "b", "g", "r"
                };
                foreach (var color in colors)
                {
                    field       = new GffData.Field();
                    field.type  = FieldTypes.BYTE;
                    field.BYTE  = Byte.MaxValue;
                    field.label = color;

                    text    = GeneralGFF.ConstructNodetext(field);
                    val     = new Sortable(text, field.label);
                    val.Tag = field;
                    part.Nodes.Add(val);
                }
                part.Expand();
            }
            node.Expand();
        }
Esempio n. 15
0
        /// <summary>
        /// Adds a Locale to a CExoLocString Field.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contextclick_AddLocale(object sender, EventArgs e)
        {
            var field = (GffData.Field)SelectedNode.Tag;

            if (field.localeflags != LocaleDialog.Loc_ALL)
            {
                using (var f = new LocaleDialog(field.localeflags))
                {
                    if (f.ShowDialog(this) == DialogResult.OK)
                    {
                        var locale = new GffData.Locale();
                        locale.local = String.Empty;

                        LocaleDialog.SetLocaleFlag(ref field.localeflags,
                                                   locale.langid = _langid,
                                                   locale.F      = _langf);

                        if (field.Locales == null)
                        {
                            field.Locales = new List <GffData.Locale>();
                        }

                        var fieldloc = new GffData.Field();
                        fieldloc.type     = FieldTypes.locale;
                        fieldloc.label    = GffData.Locale.GetLanguageString(_langid, _langf);
                        fieldloc.localeid = (uint)field.Locales.Count;

                        field.Locales.Add(locale);
                        AddField(fieldloc, locale);
                    }
                }
            }
            else
            {
                using (var f = new InfoDialog(Globals.Error, "All locales are taken."))
                    f.ShowDialog(this);
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Adds a Field to a treenode.
        /// </summary>
        /// <param name="field">a Field to add</param>
        /// <param name="parent">a treenode to add it to</param>
        /// <param name="locale">a locale if applicable</param>
        static void AddField(GffData.Field field, TreeNode parent, GffData.Locale locale = null)
        {
            // TODO: Refactor things throughout the code such that the Tag of a
            // treenode is *either* a GffData.Field *or* a GffData.Locale.

            string text = GeneralGFF.ConstructNodetext(field, locale);

            var node = new Sortable(text, field.label);

            node.Tag = field;
            parent.Nodes.Add(node);

            switch (field.type)
            {
            case FieldTypes.Struct:                     // childs can be of any Type.
            {
                List <uint> fieldids = field.Struct.fieldids;
                for (int i = 0; i != fieldids.Count; ++i)
                {
                    AddField(GffReader.Fields[(int)fieldids[i]], node);
                }
                break;
            }

            case FieldTypes.List:                     // childs are Structs.
            {
                List <uint> list = field.List;
                for (int i = 0; i != list.Count; ++i)
                {
                    // NOTE: Structs in Lists do not have a Label inside a GFF-file.
                    // so give Structs in Lists a pseudo-label for their treenode(s)
                    field        = new GffData.Field();
                    field.type   = FieldTypes.Struct;
                    field.label  = i.ToString();
                    field.Struct = GffReader.Structs[(int)list[i]];

                    AddField(field, node);
                }
                break;
            }

            case FieldTypes.CExoLocString:                     // childs are Locales.
                if (field.Locales != null)
                {
                    int locales = field.Locales.Count;
                    for (int i = 0; i != locales; ++i)
                    {
                        locale = field.Locales[i];

                        var fieldloc = new GffData.Field();
                        fieldloc.type     = FieldTypes.locale;
                        fieldloc.localeid = (uint)i;
                        fieldloc.label    = GffData.Locale.GetLanguageString(locale.langid, locale.F);

                        AddField(fieldloc, node, locale);

                        LocaleDialog.SetLocaleFlag(ref field.localeflags,
                                                   locale.langid,
                                                   locale.F);
                    }
                }
                break;
            }
        }
Esempio n. 17
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contextclick_AddDamageReduction(object sender, EventArgs e)
        {
            BeginUpdate();

            TreeNode top = TopNode;

            var field = new GffData.Field();

            field.type          = FieldTypes.Struct;
            field.label         = SelectedNode.Nodes.Count.ToString(); // Structs in Lists do not have a Label
            field.Struct        = new Struct();
            field.Struct.typeid = 2;                                   // <- that's what's in the UTCs I've looked at.

            string text = GeneralGFF.ConstructNodetext(field);
            var    node = new Sortable(text, field.label);

            node.Tag = field;
            int id = SelectedNode.Nodes.Add(node);


            field       = new GffData.Field();
            field.type  = FieldTypes.SHORT;
            field.label = "DmgRedctAmt";
            field.SHORT = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            field       = new GffData.Field();
            field.type  = FieldTypes.SHORT;
            field.label = "DmgRedctFlags";
            field.SHORT = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);


            field       = new GffData.Field();
            field.type  = FieldTypes.List;
            field.label = "DmgRedctSubList";

            text = GeneralGFF.ConstructNodetext(field);
            var list = new Sortable(text, field.label);

            list.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(list);

            field               = new GffData.Field();
            field.type          = FieldTypes.Struct;
            field.label         = "0";     // Structs in Lists do not have a Label
            field.Struct        = new Struct();
            field.Struct.typeid = 2;       // <- that's what's in the UTCs I've looked at.

            text = GeneralGFF.ConstructNodetext(field);
            var @struct = new Sortable(text, field.label);

            @struct.Tag = field;
            list.Nodes.Add(@struct);

            field       = new GffData.Field();
            field.type  = FieldTypes.SHORT;
            field.label = "DmgRedctSubType";
            field.SHORT = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            @struct.Nodes.Add(node);

            field       = new GffData.Field();
            field.type  = FieldTypes.SHORT;
            field.label = "DmgRedctType";
            field.SHORT = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            @struct.Nodes.Add(node);


            SelectedNode = SelectedNode.Nodes[id];
            SelectedNode.Expand();
            list.Expand();
            @struct.Expand();

            TopNode = top;

            _f.GffData.Changed = true;
            _f.GffData         = _f.GffData;

            EndUpdate();

            node.EnsureVisible();             // yes those calls are in a specific sequence.
        }
Esempio n. 18
0
        /// <summary>
        /// Adds an apparel-type.
        /// </summary>
        void AddApparel(string label)
        {
            BeginUpdate();

            TreeNode top = TopNode;

            var field = new GffData.Field();

            field.type          = FieldTypes.Struct;
            field.label         = label;
            field.Struct        = new Struct();
            field.Struct.typeid = 0;             // <- that's what's in the UTCs I've looked at.

            string text = GeneralGFF.ConstructNodetext(field);
            var    node = new Sortable(text, field.label);

            node.Tag = field;
            int id = SelectedNode.Nodes.Add(node);


            field               = new GffData.Field();
            field.type          = FieldTypes.Struct;
            field.label         = "ArmorTint";
            field.Struct        = new Struct();
            field.Struct.typeid = 0;             // <- that's what's in the UTCs I've looked at.

            text = GeneralGFF.ConstructNodetext(field);
            var tint = new Sortable(text, field.label);

            tint.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(tint);

            AddTints(tint);


            field       = new GffData.Field();
            field.type  = FieldTypes.BYTE;
            field.BYTE  = 0;
            field.label = "ArmorVisualType";

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            field       = new GffData.Field();
            field.type  = FieldTypes.BYTE;
            field.BYTE  = 0;
            field.label = "Variation";

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);


            SelectedNode = SelectedNode.Nodes[id];
            SelectedNode.Expand();

            TopNode = top;

            _f.GffData.Changed = true;
            _f.GffData         = _f.GffData;

            EndUpdate();

            node.EnsureVisible();             // yes those calls are in a specific sequence.
        }
Esempio n. 19
0
        /// <summary>
        /// Adds a Struct (a Class structure) to the "ClassList" List.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contextclick_AddClass(object sender, EventArgs e)
        {
            BeginUpdate();

            TreeNode top = TopNode;

            var field = new GffData.Field();

            field.type          = FieldTypes.Struct;
            field.label         = SelectedNode.Nodes.Count.ToString(); // Structs in Lists do not have a Label
            field.Struct        = new Struct();
            field.Struct.typeid = 2;                                   // <- that's what's in the UTCs I've looked at.

            string text = GeneralGFF.ConstructNodetext(field);
            var    node = new Sortable(text, field.label);

            node.Tag = field;
            int id = SelectedNode.Nodes.Add(node);


            field       = new GffData.Field();
            field.type  = FieldTypes.INT;
            field.label = "Class";
            field.INT   = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            field       = new GffData.Field();
            field.type  = FieldTypes.SHORT;
            field.label = "ClassLevel";
            field.SHORT = 1;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            for (int i = 0; i != 10; ++i)
            {
                field       = new GffData.Field();
                field.type  = FieldTypes.List;
                field.label = LABEL_PREFIX_KNOWN + i;

                text     = GeneralGFF.ConstructNodetext(field);
                node     = new Sortable(text, field.label);
                node.Tag = field;
                SelectedNode.Nodes[id].Nodes.Add(node);
            }

            for (int i = 0; i != 10; ++i)
            {
                field       = new GffData.Field();
                field.type  = FieldTypes.List;
                field.label = LABEL_PREFIX_MEMORIZED + i;

                text     = GeneralGFF.ConstructNodetext(field);
                node     = new Sortable(text, field.label);
                node.Tag = field;
                SelectedNode.Nodes[id].Nodes.Add(node);
            }

            SelectedNode = SelectedNode.Nodes[id];
            SelectedNode.Expand();

            TopNode = top;

            _f.GffData.Changed = true;
            _f.GffData         = _f.GffData;

            EndUpdate();

            node.EnsureVisible();             // yes those calls are in a specific sequence.
        }
Esempio n. 20
0
        /// <summary>
        /// Adds a Struct (an InventoryItem structure) to the "ItemList" List.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contextclick_AddInventoryItem(object sender, EventArgs e)
        {
            BeginUpdate();

            TreeNode top = TopNode;

            int id = SelectedNode.Nodes.Count;

            var field = new GffData.Field();

            field.type          = FieldTypes.Struct;
            field.label         = id.ToString();     // Structs in Lists do not have a Label
            field.Struct        = new Struct();
            field.Struct.typeid = (uint)id;          // <- that's what's in the UTCs I've looked at.

            string text = GeneralGFF.ConstructNodetext(field);
            var    node = new Sortable(text, field.label);

            node.Tag = field;
            id       = SelectedNode.Nodes.Add(node);


            field       = new GffData.Field();
            field.type  = FieldTypes.BYTE;
            field.label = "Dropable";
            field.BYTE  = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            field         = new GffData.Field();
            field.type    = FieldTypes.CResRef;
            field.label   = "EquippedRes";
            field.CResRef = String.Empty;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            field       = new GffData.Field();
            field.type  = FieldTypes.BYTE;
            field.label = "Pickpocketable";
            field.BYTE  = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            field       = new GffData.Field();
            field.type  = FieldTypes.WORD;
            field.label = "Repos_PosX";
            field.WORD  = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            field       = new GffData.Field();
            field.type  = FieldTypes.WORD;
            field.label = "Repos_PosY";
            field.WORD  = 0;

            text     = GeneralGFF.ConstructNodetext(field);
            node     = new Sortable(text, field.label);
            node.Tag = field;
            SelectedNode.Nodes[id].Nodes.Add(node);

            SelectedNode = SelectedNode.Nodes[id];
            SelectedNode.Expand();

            TopNode = top;

            _f.GffData.Changed = true;
            _f.GffData         = _f.GffData;

            EndUpdate();

            node.EnsureVisible();             // yes those calls are in a specific sequence.
        }
Esempio n. 21
0
        /// <summary>
        /// Adds a Struct (an EquippedItem structure) to the "Equip_ItemList" List.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contextclick_AddEquippedItem(object sender, EventArgs e)
        {
            GffData.Field field;

            _bitslot = 0;
            for (int i = 0; i != SelectedNode.Nodes.Count; ++i)
            {
                field     = (GffData.Field)SelectedNode.Nodes[i].Tag;
                _bitslot |= field.Struct.typeid;
            }

            using (var f = new EquippedItemDialog(_bitslot))
            {
                _bitslot = 0;
                if (f.ShowDialog(this) == DialogResult.OK)
                {
                    BeginUpdate();

                    TreeNode top = TopNode;

                    field               = new GffData.Field();
                    field.type          = FieldTypes.Struct;
                    field.label         = SelectedNode.Nodes.Count.ToString(); // Structs in Lists do not have a Label
                    field.Struct        = new Struct();
                    field.Struct.typeid = _bitslot;                            // <- that's what's in the UTCs I've looked at.

                    string text = GeneralGFF.ConstructNodetext(field);
                    var    node = new Sortable(text, field.label);
                    node.Tag = field;
                    int id = SelectedNode.Nodes.Add(node);


                    field       = new GffData.Field();
                    field.type  = FieldTypes.BYTE;
                    field.label = "Dropable";
                    field.BYTE  = 0;

                    text     = GeneralGFF.ConstructNodetext(field);
                    node     = new Sortable(text, field.label);
                    node.Tag = field;
                    SelectedNode.Nodes[id].Nodes.Add(node);

                    field         = new GffData.Field();
                    field.type    = FieldTypes.CResRef;
                    field.label   = "EquippedRes";
                    field.CResRef = String.Empty;

                    text     = GeneralGFF.ConstructNodetext(field);
                    node     = new Sortable(text, field.label);
                    node.Tag = field;
                    SelectedNode.Nodes[id].Nodes.Add(node);

                    field       = new GffData.Field();
                    field.type  = FieldTypes.BYTE;
                    field.label = "Pickpocketable";
                    field.BYTE  = 0;

                    text     = GeneralGFF.ConstructNodetext(field);
                    node     = new Sortable(text, field.label);
                    node.Tag = field;
                    SelectedNode.Nodes[id].Nodes.Add(node);

                    field       = new GffData.Field();
                    field.type  = FieldTypes.WORD;
                    field.label = "Repos_PosX";
                    field.WORD  = 0;

                    text     = GeneralGFF.ConstructNodetext(field);
                    node     = new Sortable(text, field.label);
                    node.Tag = field;
                    SelectedNode.Nodes[id].Nodes.Add(node);

                    field       = new GffData.Field();
                    field.type  = FieldTypes.WORD;
                    field.label = "Repos_PosY";
                    field.WORD  = 0;

                    text     = GeneralGFF.ConstructNodetext(field);
                    node     = new Sortable(text, field.label);
                    node.Tag = field;
                    SelectedNode.Nodes[id].Nodes.Add(node);


                    // keep the List's nodes in the correct sequence ->
                    // they are arranged by Struct.typeid ascending

                    int i;                     // iterator for the sortables
                    int j;                     // tracker for the node # added

                    // store all the sortable Structs in the List ->
                    // NOTE: This is not an ideal routine. Because it adds all
                    // the nodes to the tree, then removes them, then adds them
                    // all again. It should, rather, just construct the Struct
                    // and its fields, then add the Struct to the tree.

                    var sortables = new List <Sortable>();
                    for (i = 0; i != SelectedNode.Nodes.Count; ++i)
                    {
                        sortables.Add((Sortable)SelectedNode.Nodes[i]);
                    }

                    SelectedNode.Nodes.Clear();                     // NOTE: 'SelectedNode' is the "Equip_ItemList" list-field.


                    // re-add the sortables before the added sortable ->
                    i = j = 0;
                    while (i != sortables.Count)
                    {
                        field = (GffData.Field)sortables[i].Tag;
                        if (field.Struct.typeid < _bitslot)
                        {
                            // NOTE: 'field.label' doesn't need to be changed here
                            sortables[i].Text = GeneralGFF.ConstructNodetextEquipped(field);
                            SelectedNode.Nodes.Add(sortables[i]);
                            j = i;
                        }
                        ++i;
                    }

                    id = ++j;

                    // re-add the last sortable into the sequence ->
                    // replace vals that were set above for the Struct's label and its Sortable's text and label
                    field       = (GffData.Field)sortables[sortables.Count - 1].Tag;
                    field.label = sortables[sortables.Count - 1]._label = j.ToString();
                    sortables[sortables.Count - 1].Text = GeneralGFF.ConstructNodetextEquipped(field);
                    SelectedNode.Nodes.Add(sortables[sortables.Count - 1]);


                    // re-add the sortables that go after the added sortable ->
                    i = 0;
                    while (i != sortables.Count)
                    {
                        field = (GffData.Field)sortables[i].Tag;
                        if (field.Struct.typeid > _bitslot)
                        {
                            field.label       = sortables[i]._label = (++j).ToString();
                            sortables[i].Text = GeneralGFF.ConstructNodetextEquipped(field);
                            SelectedNode.Nodes.Add(sortables[i]);
                        }
                        ++i;
                    }

                    SelectedNode = SelectedNode.Nodes[id];
                    SelectedNode.Expand();

                    TopNode = top;

                    _f.GffData.Changed = true;
                    _f.GffData         = _f.GffData;

                    EndUpdate();

                    node.EnsureVisible();                     // yes those calls are in a specific sequence.
                }
            }
        }
Esempio n. 22
0
        /// <summary>
        /// Adds a Struct (a Variable structure) to the "VarTable" List.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contextclick_AddVariable(object sender, EventArgs e)
        {
            using (var dialog = new VariableDialog())
            {
                if (dialog.ShowDialog(this) == DialogResult.OK)
                {
                    BeginUpdate();

                    TreeNode top = TopNode;

                    var field = new GffData.Field();
                    field.type          = FieldTypes.Struct;
                    field.label         = SelectedNode.Nodes.Count.ToString(); // Structs in Lists do not have a Label
                    field.Struct        = new Struct();
                    field.Struct.typeid = 0;                                   // <- that's what's in the UTCs I've looked at.

                    string text = GeneralGFF.ConstructNodetext(field);
                    var    node = new Sortable(text, field.label);
                    node.Tag = field;
                    int id = SelectedNode.Nodes.Add(node);


                    field            = new GffData.Field();
                    field.type       = FieldTypes.CExoString;
                    field.label      = "Name";
                    field.CExoString = _varLabel;

                    text     = GeneralGFF.ConstructNodetext(field);
                    node     = new Sortable(text, field.label);
                    node.Tag = field;
                    SelectedNode.Nodes[id].Nodes.Add(node);

                    field       = new GffData.Field();
                    field.type  = FieldTypes.DWORD;
                    field.label = "Type";
                    field.DWORD = _varType;

                    text     = GeneralGFF.ConstructNodetext(field);
                    node     = new Sortable(text, field.label);
                    node.Tag = field;
                    SelectedNode.Nodes[id].Nodes.Add(node);

                    field       = new GffData.Field();
                    field.label = "Value";

                    switch (_varType)                     // TODO: delete the nodes above or put this above there
                    {
                    case VariableDialog.Type_non:         // not stable in toolset. is Disabled in the dialog
                        return;

                    case VariableDialog.Type_INT:
                        field.type = FieldTypes.INT;
                        field.INT  = Int32.Parse(_varValue);
                        break;

                    case VariableDialog.Type_FLOAT:
                        field.type  = FieldTypes.FLOAT;
                        field.FLOAT = Single.Parse(_varValue);
                        break;

                    case VariableDialog.Type_STRING:
                        field.type       = FieldTypes.CExoString;
                        field.CExoString = _varValue;
                        break;

                    case VariableDialog.Type_LOCATION:                                  // not stable in toolset. is Disabled in the dialog
                        return;

                    case VariableDialog.Type_UINT:                                      // and I can't see this being useful at all.
                        field.type  = FieldTypes.DWORD;
                        field.DWORD = UInt32.Parse(_varValue);
                        break;
                    }

                    text     = GeneralGFF.ConstructNodetext(field);
                    node     = new Sortable(text, field.label);
                    node.Tag = field;
                    SelectedNode.Nodes[id].Nodes.Add(node);

                    SelectedNode = SelectedNode.Nodes[id];
                    SelectedNode.Expand();

                    TopNode = top;

                    _f.GffData.Changed = true;
                    _f.GffData         = _f.GffData;

                    EndUpdate();

                    node.EnsureVisible();                     // yes those calls are in a specific sequence.
                }
            }
        }
Esempio n. 23
0
/*		static readonly List<uint> _fieldids = new List<uint>();
 *              /// <summary>
 *              ///
 *              /// </summary>
 *              internal static List<uint> FieldIds
 *              { get { return _fieldids; } } */
        #endregion Properties (static)


        #region Methods (static)
        /// <summary>
        /// Reads a GFF-file and parses out its data to a GFFData object.
        /// @note Sections will be extracted in a non-arbitrary sequence because
        /// the data in a specific section could rely on the data in a different
        /// section. The order I have chosen is:
        /// 1. Header data (ofc)
        /// 2. FieldIndices
        /// 3. Structs - relies on FieldIndices
        /// 4. Labels
        /// 5. Fields - relies on Structs and Labels and extracts FieldData and ListIndices
        /// </summary>
        /// <param name="pfe">path-file-extension - ensure file exists before call</param>
        internal static GffData ReadGFFfile(string pfe)
        {
            Structs.Clear();             // Structs and Fields will be cleared after load completes
            Fields.Clear();              // but do it here (before load starts) also - jic.

            byte[] bytes = FileService.ReadFile(pfe);
            if (bytes != null)
            {
                if (bytes.Length != 0)
                {
                    uint pos = 0;
                    uint b;

                    var buffer = new byte[8];
                    for (b = 0; b != 8; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    string ver = Encoding.ASCII.GetString(buffer, 0, buffer.Length);

                    if (ver.Substring(3) != Globals.SupportedVersion)
                    {
                        FileService.error("That is not a version 3.2 GFF file.");
                        return(null);
                    }


                    bool le = BitConverter.IsLittleEndian;                     // hardware architecture

                    var data = new GffData(pfe);

                    data.TypeVer = ver;
                    data.Type    = GffData.GetGffType(ver.Substring(0, 3));

                    data.Latest            = File.GetLastWriteTime(pfe);
                    FileWatchDialog.Bypass = false;


// HEADER METADATA ->
                    pos    = head_StructOffset;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint StructOffset = BitConverter.ToUInt32(buffer, 0);
                    //logfile.Log("StructOffset= " + StructOffset);

                    // The Struct-section will always start at 56-bytes (0x38)
                    if (StructOffset != Globals.Length_HEADER)
                    {
                        FileService.error("That does not appear to be a GFF file.");
                        return(null);
                    }

                    pos    = head_StructCount;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint StructCount = BitConverter.ToUInt32(buffer, 0);                     // count of elements
                    //logfile.Log("StructCount= " + StructCount);


                    pos    = head_FieldOffset;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint FieldOffset = BitConverter.ToUInt32(buffer, 0);
                    //logfile.Log("FieldOffset= " + FieldOffset);


                    pos    = head_FieldCount;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint FieldCount = BitConverter.ToUInt32(buffer, 0);                     // count of elements
                    //logfile.Log("FieldCount= " + FieldCount);


                    pos    = head_LabelOffset;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint LabelOffset = BitConverter.ToUInt32(buffer, 0);
                    //logfile.Log("LabelOffset= " + LabelOffset);


                    pos    = head_LabelCount;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint LabelCount = BitConverter.ToUInt32(buffer, 0);                     // count of elements
                    //logfile.Log("LabelCount= " + LabelCount);


                    pos    = head_FieldDataOffset;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint FieldDataOffset = BitConverter.ToUInt32(buffer, 0);
                    //logfile.Log("FieldDataOffset= " + FieldDataOffset);


                    pos    = head_FieldDataLength;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint FieldDataCount = BitConverter.ToUInt32(buffer, 0);                     // count of bytes (not used.)
                    //logfile.Log("FieldDataCount= " + FieldDataCount);


                    pos    = head_FieldIndicesOffset;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint FieldIndicesOffset = BitConverter.ToUInt32(buffer, 0);
                    //logfile.Log("FieldIndicesOffset= " + FieldIndicesOffset);


                    pos    = head_FieldIndicesLength;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint FieldIndicesCount = BitConverter.ToUInt32(buffer, 0);                     // count of bytes
                    //logfile.Log("FieldIndicesCount= " + FieldIndicesCount);


                    pos    = head_ListIndicesOffset;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint ListIndicesOffset = BitConverter.ToUInt32(buffer, 0);
                    //logfile.Log("ListIndicesOffset= " + ListIndicesOffset);


                    pos    = head_ListIndicesLength;
                    buffer = new byte[4];
                    for (b = 0; b != 4; ++b)
                    {
                        buffer[b] = bytes[pos++];
                    }

                    if (!le)
                    {
                        Array.Reverse(buffer);
                    }
                    uint ListIndicesCount = BitConverter.ToUInt32(buffer, 0);                     // count of bytes (not used.)
                    //logfile.Log("ListIndicesCount= " + ListIndicesCount);


                    //logfile.Log("");

// FIELDID DATA -> contains the FieldIds of Structs that contain > 1 field (is req'd for parsing Structs)
// - a list of DWORD ids into the Fields section
                    //logfile.Log("FIELDIDS");
                    //int fid = 0; // log

                    var fieldids = new List <uint>();

                    pos = FieldIndicesOffset;
                    while (pos != FieldIndicesOffset + FieldIndicesCount)
                    {
                        //logfile.Log(". start= " + FieldIndicesOffset + " stop= " + (FieldIndicesOffset + FieldIndicesCount));
                        //logfile.Log(". fid #" + fid++);

                        buffer = new byte[4];                         // 4-byte DWORD - field id
                        for (b = 0; b != 4; ++b)
                        {
                            //logfile.Log(". . pos= " + pos);
                            buffer[b] = bytes[pos++];
                        }

                        if (!le)
                        {
                            Array.Reverse(buffer);
                        }
                        fieldids.Add(BitConverter.ToUInt32(buffer, 0));                         // WARNING: There is no safety on the count below.
                    }


// STRUCT DATA ->
// - DWORD type-id
// - DWORD dataordataoffset
// - DWORD fieldcount
                    uint fields, idoroffset, i, j;

                    pos = StructOffset;
                    for (i = 0; i != StructCount; ++i)
                    {
                        //logfile.Log("Struct #" + i);
                        var st = new Struct();

                        buffer = new byte[4];                         // type-id ->
                        for (b = 0; b != 4; ++b)
                        {
                            buffer[b] = bytes[pos++];
                        }

                        if (!le)
                        {
                            Array.Reverse(buffer);
                        }
                        st.typeid = BitConverter.ToUInt32(buffer, 0);
                        //logfile.Log(". typid= " + st.typeid);

                        buffer = new byte[4];                         // dataordataoffset ->
                        for (b = 0; b != 4; ++b)
                        {
                            buffer[b] = bytes[pos++];
                        }

                        if (!le)
                        {
                            Array.Reverse(buffer);
                        }
                        idoroffset = BitConverter.ToUInt32(buffer, 0);                          // if fields=1 -> id into the FieldArray
                        // if fields>1 -> offset into FieldIndices -> list of ids into the FieldArray

                        buffer = new byte[4];                         // fieldcount ->
                        for (b = 0; b != 4; ++b)
                        {
                            buffer[b] = bytes[pos++];
                        }

                        if (!le)
                        {
                            Array.Reverse(buffer);
                        }
                        fields = BitConverter.ToUInt32(buffer, 0);
                        //logfile.Log(". fields= " + fields);

                        st.fieldids = new List <uint>();
                        if (fields == 1)                                        // get the FieldId directly w/ the Struct's 'idoroffset' id ->
                        {
                            //logfile.Log(". . idoroffset/id= " + idoroffset);
                            //logfile.Log(". . data._fields.Count= " + data._fields.Count);
                            st.fieldids.Add(idoroffset);
                        }
                        else if (fields > 1)                            // get the FieldIds out of the FieldIndices w/ the 'idoroffset' offset ->
                        {
                            uint fieldid;
                            for (j = 0; j != fields; ++j)
                            {
                                //logfile.Log(". . [" + j + "] idoroffset/offset= " + idoroffset + " -> fieldids id= " + (idoroffset / 4 + j));
                                //logfile.Log(". . data._fieldids Length= " + (data._fieldids.Count * 4));
                                //logfile.Log(". . data._fields.Count= " + data._fields.Count);

                                fieldid = fieldids[(int)(idoroffset / Globals.Length_DWORD + j)];                                       // 4 bytes in each DWORD (ie. convert offset to id id)
                                //logfile.Log(". . fieldid= " + fieldid);
                                st.fieldids.Add(fieldid);                                                                               // isn't the GFF format wonderful ... at least it works
                            }                                                                                                           // the Bioware documentation could be better.
                        }                                                                                                               // Ps. it contains inaccurate and unspecific info

                        Structs.Add(st);
                    }


// LABEL DATA -> contains Labels for the Fields (is req'd for parsing Fields)
// - each label shall be unique across the entire GFF data
// - 16-CHAR
                    var    labels = new List <string>();
                    string label;

                    pos = LabelOffset;
                    for (i = 0; i != LabelCount; ++i)
                    {
                        buffer = new byte[Globals.Length_LABEL];                         // 16-byte CHAR(s) - label length
                        for (b = 0; b != Globals.Length_LABEL; ++b)
                        {
                            buffer[b] = bytes[pos++];
                        }

                        label = Encoding.ASCII.GetString(buffer, 0, buffer.Length).TrimEnd('\0');
                        labels.Add(label);
                    }


// FIELD DATA ->
// - the doc contradicts itself by saying that the TopLevelStruct is the 1st
//   entry in the Fields section but that the Fields section does not contain
//   the TopLevelStruct ... the latter appears to be correct: the first Field in
//   a toolset-written FieldsArray is "Description" eg.
// - DWORD datatype
// - DWORD label-id
// - DWORD dataordataoffset
//   - if BYTE,CHAR,WORD,SHORT,DWORD,INT,FLOAT -> dataordataoffset is a value.
//   - if DWORD64,INT64,DOUBLE,CExoString,CResRef,CExoLocString -> dataordataoffset
//     is an offset from the start of the FieldDataBlock section to complex data:
//     - DWORD64       8-bytes
//     - INT64         8-bytes
//     - DOUBLE        8-bytes
//     - CExoString    DWORD (length) + chars
//     - CExoLocString DWORD (total length) + DWORD (strref) + DWORD (stringcount) + [INT (id) + INT (length) + chars]
//     - CResRef       1-byte (length) + chars (lowercase)
//     - VOID          arbitrary
//   - if Struct -> dataordataoffset is an id into the Struct section.
//   - if List -> dataordataoffset is an offset from the start of the ListIndices
//     section to an array of DWORDs, the first of which is the count of DWORDS
//     that follow, which are ids into the Struct section.

                    uint offset, length, count;

                    pos = FieldOffset;
                    for (i = 0; i != FieldCount; ++i)
                    {
                        var field = new GffData.Field();


                        buffer = new byte[4];                         // 4-byte DWORD - field type
                        for (b = 0; b != 4; ++b)
                        {
                            buffer[b] = bytes[pos++];
                        }

                        if (!le)
                        {
                            Array.Reverse(buffer);
                        }
                        field.type = (FieldTypes)BitConverter.ToUInt32(buffer, 0);


                        buffer = new byte[4];                         // 4-byte DWORD - field label id
                        for (b = 0; b != 4; ++b)
                        {
                            buffer[b] = bytes[pos++];
                        }

                        if (!le)
                        {
                            Array.Reverse(buffer);
                        }
                        field.label = labels[(int)BitConverter.ToUInt32(buffer, 0)];
                        //logfile.Log("label= " + field.label);


                        buffer = new byte[4];                                   // 4-byte DWORD - field data (val, is not a DWORD per se) or data
                        for (b = 0; b != 4; ++b)                                // offset into (a) DataBlock or (b) ListIds or id into (c) Structs
                        {
                            buffer[b] = bytes[pos++];
                        }


                        switch (field.type)
                        {
                        // WARNING: non-Complex types whose size is less than or
                        // equal to 4-bytes are (according to the doc) contained
                        // in the first byte(s) of the dataordataoffset 'DWORD'.

                        case FieldTypes.BYTE:
                            field.BYTE = buffer[0];
                            break;

                        case FieldTypes.CHAR:
                        {
                            var a = (sbyte[])(object)new[] { buffer[0] };
                            field.CHAR = a[0];
                            break;
                        }

                        case FieldTypes.WORD:
                        {
                            var a = new byte[2];
                            if (le)
                            {
                                a[0] = buffer[0];
                                a[1] = buffer[1];
                            }
                            else
                            {
                                a[0] = buffer[1];
                                a[1] = buffer[0];
                            }

                            field.WORD = BitConverter.ToUInt16(a, 0);
                            break;
                        }

                        case FieldTypes.SHORT:
                        {
                            var a = new byte[2];
                            if (le)
                            {
                                a[0] = buffer[0];
                                a[1] = buffer[1];
                            }
                            else
                            {
                                a[0] = buffer[1];
                                a[1] = buffer[0];
                            }

                            field.SHORT = BitConverter.ToInt16(a, 0);
                            break;
                        }

                        case FieldTypes.DWORD:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            field.DWORD = BitConverter.ToUInt32(buffer, 0);
                            break;

                        case FieldTypes.INT:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            field.INT = BitConverter.ToInt32(buffer, 0);
                            break;

                        case FieldTypes.DWORD64:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            offset = FieldDataOffset + BitConverter.ToUInt32(buffer, 0);
                            buffer = new byte[8];
                            for (b = 0; b != 8; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            field.DWORD64 = BitConverter.ToUInt64(buffer, 0);
                            break;

                        case FieldTypes.INT64:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            offset = FieldDataOffset + BitConverter.ToUInt32(buffer, 0);
                            buffer = new byte[8];
                            for (b = 0; b != 8; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            field.INT64 = BitConverter.ToInt64(buffer, 0);
                            break;

                        case FieldTypes.FLOAT:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            field.FLOAT = BitConverter.ToSingle(buffer, 0);
                            break;

                        case FieldTypes.DOUBLE:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            offset = FieldDataOffset + BitConverter.ToUInt32(buffer, 0);
                            buffer = new byte[8];
                            for (b = 0; b != 8; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            field.DOUBLE = BitConverter.ToDouble(buffer, 0);
                            break;

                        case FieldTypes.CResRef:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            offset = FieldDataOffset + BitConverter.ToUInt32(buffer, 0);
                            length = bytes[offset];                                     // 1-byte size

                            ++offset;
                            buffer = new byte[(int)length];
                            for (b = 0; b != length; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            field.CResRef = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
                            break;

                        case FieldTypes.CExoString:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            offset = FieldDataOffset + BitConverter.ToUInt32(buffer, 0);

                            buffer = new byte[4];
                            for (b = 0; b != 4; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            length = BitConverter.ToUInt32(buffer, 0);                                     // 4-byte size

                            buffer = new byte[(int)length];
                            for (b = 0; b != length; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            field.CExoString = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                            field.CExoString = field.CExoString.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n");
                            break;

                        case FieldTypes.CExoLocString:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            offset = FieldDataOffset + BitConverter.ToUInt32(buffer, 0);

                            buffer = new byte[4];                                                                                       // total length (not incl/ these 4 bytes) ->
                            for (b = 0; b != 4; ++b)                                                                                    // aka Pointless. just advance the offset val
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            length = BitConverter.ToUInt32(buffer, 0);                                     // 4-byte size

                            buffer = new byte[4];                                                          // strref (-1 no strref)
                            for (b = 0; b != 4; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            field.CExoLocStrref = BitConverter.ToUInt32(buffer, 0);                                     // 4-byte size

                            buffer = new byte[4];                                                                       // substring count
                            for (b = 0; b != 4; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            count = BitConverter.ToUInt32(buffer, 0);                                     // 4-byte size

                            if (count != 0)
                            {
                                field.Locales = new List <GffData.Locale>();

                                //logfile.Log("label= " + field.label);
                                for (j = 0; j != count; ++j)
                                {
                                    var locale = new GffData.Locale();

                                    buffer = new byte[4];                                             // langid
                                    for (b = 0; b != 4; ++b)
                                    {
                                        buffer[b] = bytes[offset++];
                                    }

                                    if (!le)
                                    {
                                        Array.Reverse(buffer);
                                    }
                                    locale.SetLocaleLanguage(BitConverter.ToUInt32(buffer, 0));

                                    buffer = new byte[4];                                             // stringlength
                                    for (b = 0; b != 4; ++b)
                                    {
                                        buffer[b] = bytes[offset++];
                                    }

                                    if (!le)
                                    {
                                        Array.Reverse(buffer);
                                    }
                                    length = BitConverter.ToUInt32(buffer, 0);
                                    //logfile.Log("length= " + length);

                                    buffer = new byte[(int)length];
                                    for (b = 0; b != length; ++b)
                                    {
                                        buffer[b] = bytes[offset++];
                                    }

                                    locale.local = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                                    locale.local = locale.local.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n");
                                    //logfile.Log("local= " + locale.local);

                                    field.Locales.Add(locale);
                                }
                            }
                            break;

                        case FieldTypes.VOID:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            offset = FieldDataOffset + BitConverter.ToUInt32(buffer, 0);
                            buffer = new byte[4];
                            for (b = 0; b != 4; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            length = BitConverter.ToUInt32(buffer, 0);

                            field.VOID = new byte[(int)length];

                            for (j = 0; j != length; ++j)
                            {
                                field.VOID[j] = bytes[offset++];
                            }

                            break;

                        case FieldTypes.List:                                 // a list-type Field is an offset into the FieldIndices; the later contains a list of StructIds.
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            offset = ListIndicesOffset + BitConverter.ToUInt32(buffer, 0); // offset into the (not)FieldIndices(not) -> try ListIndices

                            buffer = new byte[4];                                          // 4-byte DWORD - count of structids
                            for (b = 0; b != 4; ++b)
                            {
                                buffer[b] = bytes[offset++];
                            }

                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            count = BitConverter.ToUInt32(buffer, 0);

                            var list = new List <uint>();
                            for (j = 0; j != count; ++j)
                            {
                                buffer = new byte[4];                                         // 4-byte DWORD - structid
                                for (b = 0; b != 4; ++b)
                                {
                                    buffer[b] = bytes[offset++];
                                }

                                if (!le)
                                {
                                    Array.Reverse(buffer);
                                }
                                list.Add(BitConverter.ToUInt32(buffer, 0));
                            }
                            field.List = list;
                            break;

                        case FieldTypes.Struct:
                            if (!le)
                            {
                                Array.Reverse(buffer);
                            }
                            field.Struct = Structs[(int)BitConverter.ToUInt32(buffer, 0)];                                     // NOTE: That is an id into the Structs not an offset.
                            break;
                        }

                        Fields.Add(field);
                    }
                    return(data);
                }

                FileService.error("That file has no data.");
            }
            return(null);
        }