Пример #1
0
        // This reads the vertices
        private Dictionary <int, Vertex> ReadVertices(MapSet map, UniversalParser textmap)
        {
            Dictionary <int, Vertex> link;

            // Get list of entries
            List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "vertex");

            // Create lookup table
            link = new Dictionary <int, Vertex>(collections.Count);

            // Go for all collections
            map.SetCapacity(map.Vertices.Count + collections.Count, 0, 0, 0, 0);
            for (int i = 0; i < collections.Count; i++)
            {
                // Read fields
                UniversalCollection c = collections[i];
                string where = "vertex " + i;
                float x = GetCollectionEntry <float>(c, "x", true, 0.0f, where);
                float y = GetCollectionEntry <float>(c, "y", true, 0.0f, where);

                // Create new item
                Vertex v = map.CreateVertex(new Vector2D(x, y));
                if (v != null)
                {
                    // Custom fields
                    ReadCustomFields(c, v, "vertex");

                    // Add it to the lookup table
                    link.Add(i, v);
                }
            }

            // Return lookup table
            return(link);
        }
Пример #2
0
        // This will load a configuration from string
        public bool InputConfiguration(string data)
        {
            // Remove returns and tabs because the
            // parser only uses newline for new lines.
            data = data.Replace("\r", "");
            data = data.Replace("\t", "");

            // Clear errors
            ClearError();

            // Parse the data to the root structure
            int pos  = 0;
            int line = 1;

            root = InputStructure(ref data, ref pos, ref line);

            // Return true when done, false when errors occurred
            if (cpErrorResult == 0)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #3
0
        // This reads a single sidedef and connects it to the given linedef
        private void ReadSidedef(MapSet map, UniversalCollection sc, Linedef ld,
                                 bool front, Dictionary <int, Sector> sectorlink, int index)
        {
            // Read fields
            string where = "linedef " + ld.Index + (front ? " front sidedef " : " back sidedef ") + index;
            int    offsetx = GetCollectionEntry <int>(sc, "offsetx", false, 0, where);
            int    offsety = GetCollectionEntry <int>(sc, "offsety", false, 0, where);
            string thigh   = GetCollectionEntry <string>(sc, "texturetop", false, "-", where);
            string tlow    = GetCollectionEntry <string>(sc, "texturebottom", false, "-", where);
            string tmid    = GetCollectionEntry <string>(sc, "texturemiddle", false, "-", where);
            int    sector  = GetCollectionEntry <int>(sc, "sector", true, 0, where);

            // Create sidedef
            if (sectorlink.ContainsKey(sector))
            {
                Sidedef s = map.CreateSidedef(ld, front, sectorlink[sector]);
                if (s != null)
                {
                    s.Update(offsetx, offsety, thigh, tmid, tlow);

                    // Custom fields
                    ReadCustomFields(sc, s, "sidedef");
                }
            }
            else
            {
                General.ErrorLogger.Add(ErrorType.Warning, "Sidedef references invalid sector " + sector + ". Sidedef has been removed.");
            }
        }
        // This adds sectors
        private void WriteSectors(ICollection <Sector> sectors, UniversalParser textmap)
        {
            // Go for all sectors
            foreach (Sector s in sectors)
            {
                // Make collection
                UniversalCollection coll = new UniversalCollection();
                coll.Add("heightfloor", s.FloorHeight);
                coll.Add("heightceiling", s.CeilHeight);
                coll.Add("texturefloor", s.FloorTexture);
                coll.Add("textureceiling", s.CeilTexture);
                coll.Add("lightlevel", s.Brightness);
                if (s.Effect != 0)
                {
                    coll.Add("special", s.Effect);
                }
                if (s.Tag != 0)
                {
                    coll.Add("id", s.Tag);
                }
                coll.Comment = s.Index.ToString();

                // Add custom fields
                AddCustomFields(s, "sector", coll);

                // Store
                textmap.Root.Add("sector", coll);
            }
        }
        // This adds vertices
        private void WriteVertices(ICollection <Vertex> vertices, UniversalParser textmap)
        {
            // Go for all vertices
            foreach (Vertex v in vertices)
            {
                // Make collection
                UniversalCollection coll = new UniversalCollection();
                coll.Add("x", v.Position.x);
                coll.Add("y", v.Position.y);
                if (!float.IsNaN(v.ZCeiling))
                {
                    coll.Add("zceiling", v.ZCeiling);                                          //mxd
                }
                if (!float.IsNaN(v.ZFloor))
                {
                    coll.Add("zfloor", v.ZFloor);                                        //mxd
                }
                coll.Comment = v.Index.ToString();

                // Add custom fields
                AddCustomFields(v, "vertex", coll);

                // Store
                textmap.Root.Add("vertex", coll);
            }
        }
Пример #6
0
        // ano - this returns all the unidentified data for preservation
        private void ReadUnidentifiedEntries(MapSet map, UniversalParser textmap)
        {
            UniversalCollection root         = textmap.Root;
            UniversalCollection unidentified = new UniversalCollection();

            foreach (UniversalEntry e in root)
            {
                switch (e.Key)
                {
                case "namespace":
                case "vertex":
                case "thing":
                case "linedef":
                case "sector":
                case "sidedef":
                    break;

                default:
                    unidentified.Add(e);
                    break;
                } // switch
            }     // foreach

            map.UnidentifiedUDMF = unidentified;
        } // ReadUnidentifiedEntries
        // This reads the sectors
        private Dictionary <int, Sector> ReadSectors(MapSet map, UniversalParser textmap)
        {
            Dictionary <int, Sector> link;

            // Get list of entries
            List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector");

            // Create lookup table
            link = new Dictionary <int, Sector>(collections.Count);

            // Go for all collections
            map.SetCapacity(0, 0, 0, map.Sectors.Count + collections.Count, 0);
            for (int i = 0; i < collections.Count; i++)
            {
                // Read fields
                UniversalCollection c = collections[i];
                string where = "sector " + i;
                int[]  colors  = new int[Sector.NUM_COLORS];
                int    hfloor  = GetCollectionEntry <int>(c, "heightfloor", false, 0, where);
                int    hceil   = GetCollectionEntry <int>(c, "heightceiling", false, 0, where);
                string tfloor  = GetCollectionEntry <string>(c, "texturefloor", true, "-", where);
                string tceil   = GetCollectionEntry <string>(c, "textureceiling", true, "-", where);
                int    bright  = GetCollectionEntry <int>(c, "lightlevel", false, 160, where);
                int    special = GetCollectionEntry <int>(c, "special", false, 0, where);
                int    tag     = GetCollectionEntry <int>(c, "id", false, 0, where);

                // villsa 9/14/11 (builder64)
                colors[0] = GetCollectionEntry <int>(c, "color1", false, 0, where);
                colors[1] = GetCollectionEntry <int>(c, "color2", false, 0, where);
                colors[2] = GetCollectionEntry <int>(c, "color3", false, 0, where);
                colors[3] = GetCollectionEntry <int>(c, "color4", false, 0, where);
                colors[4] = GetCollectionEntry <int>(c, "color5", false, 0, where);

                // villsa 9/13/11 - Flags
                Dictionary <string, bool> stringflags = new Dictionary <string, bool>();
                foreach (KeyValuePair <string, string> flag in General.Map.Config.SectorFlags)
                {
                    stringflags[flag.Key] = GetCollectionEntry <bool>(c, flag.Key, false, false, where);
                }

                // Create new item
                Sector s = map.CreateSector();
                if (s != null)
                {
                    s.Update(stringflags, hfloor, hceil, tfloor, tceil, special, tag, colors);

                    // Custom fields
                    ReadCustomFields(c, s, "sector");

                    // Add it to the lookup table
                    link.Add(i, s);
                }
            }

            // Return lookup table
            return(link);
        }
Пример #8
0
        // This reads the things
        private void ReadThings(MapSet map, UniversalParser textmap)
        {
            // Get list of entries
            List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "thing");

            // Go for all collections
            map.SetCapacity(0, 0, 0, 0, map.Things.Count + collections.Count);
            for (int i = 0; i < collections.Count; i++)
            {
                // Read fields
                UniversalCollection c = collections[i];
                int[] args            = new int[Linedef.NUM_ARGS];
                string where = "thing " + i;
                float x        = GetCollectionEntry <float>(c, "x", true, 0.0f, where);
                float y        = GetCollectionEntry <float>(c, "y", true, 0.0f, where);
                float height   = GetCollectionEntry <float>(c, "height", false, 0.0f, where);
                int   tag      = GetCollectionEntry <int>(c, "id", false, 0, where);
                int   angledeg = GetCollectionEntry <int>(c, "angle", false, 0, where);
                int   type     = GetCollectionEntry <int>(c, "type", true, 0, where);
                int   special  = GetCollectionEntry <int>(c, "special", false, 0, where);
                args[0] = GetCollectionEntry <int>(c, "arg0", false, 0, where);
                args[1] = GetCollectionEntry <int>(c, "arg1", false, 0, where);
                args[2] = GetCollectionEntry <int>(c, "arg2", false, 0, where);
                args[3] = GetCollectionEntry <int>(c, "arg3", false, 0, where);
                args[4] = GetCollectionEntry <int>(c, "arg4", false, 0, where);

                // Flags
                Dictionary <string, bool> stringflags = new Dictionary <string, bool>();
                foreach (KeyValuePair <string, string> flag in General.Map.Config.ThingFlags)
                {
                    stringflags[flag.Key] = GetCollectionEntry <bool>(c, flag.Key, false, false, where);
                }
                foreach (FlagTranslation ft in General.Map.Config.ThingFlagsTranslation)
                {
                    foreach (string field in ft.Fields)
                    {
                        stringflags[field] = GetCollectionEntry <bool>(c, field, false, false, where);
                    }
                }

                // Create new item
                Thing t = map.CreateThing();
                if (t != null)
                {
                    t.Update(type, x, y, height, angledeg, stringflags, tag, special, args);

                    // Custom fields
                    ReadCustomFields(c, t, "thing");
                }
            }
        }
Пример #9
0
        // This validates and returns an entry
        private T GetCollectionEntry <T>(UniversalCollection c, string entryname, bool required, T defaultvalue, string where)
        {
            T    result = default(T);
            bool found  = false;

            // Find the entry
            foreach (UniversalEntry e in c)
            {
                // Check if matches
                if (e.Key == entryname)
                {
                    // Let's be kind and cast any int to a float if needed
                    if ((typeof(T) == typeof(float)) &&
                        (e.Value.GetType() == typeof(int)))
                    {
                        // Make it a float
                        object fvalue = (float)(int)e.Value;
                        result = (T)fvalue;
                    }
                    else
                    {
                        // Verify type
                        e.ValidateType(typeof(T));

                        // Found it!
                        result = (T)e.Value;
                    }

                    // Done
                    found = true;
                }
            }

            // Not found?
            if (!found)
            {
                // Report error when entry is required!
                if (required)
                {
                    General.ErrorLogger.Add(ErrorType.Error, "Error while reading UDMF map data: Missing required field '" + entryname + "' at " + where + ".");
                }

                // Make default entry
                result = defaultvalue;
            }

            // Return result
            return(result);
        }
Пример #10
0
        // This makes a list of all collections with the given name
        private List <UniversalCollection> GetNamedCollections(UniversalCollection collection, string entryname)
        {
            List <UniversalCollection> list = new List <UniversalCollection>();

            // Make list
            foreach (UniversalEntry e in collection)
            {
                if ((e.Value is UniversalCollection) && (e.Key == entryname))
                {
                    list.Add(e.Value as UniversalCollection);
                }
            }

            return(list);
        }
Пример #11
0
        // This makes a list of all collections with the given name
        private static List <UniversalCollection> GetNamedCollections(UniversalCollection collection, string entryname)
        {
            List <UniversalCollection> list = new List <UniversalCollection>();

            // Make list
            foreach (UniversalEntry e in collection)
            {
                UniversalCollection uc = e.Value as UniversalCollection;
                if (uc != null && e.Key == entryname)
                {
                    list.Add(uc);
                }
            }

            return(list);
        }
Пример #12
0
        // This will load a configuration from string
        public bool InputConfiguration(string[] data)
        {
            // Clear errors
            ClearError();

            // Parse the data to the root structure
            int pos  = 0;
            int line = 0;                                                              //mxd

            matches = new Dictionary <string, UniversalEntry>(StringComparer.Ordinal); //mxd
            key     = new StringBuilder(16);                                           //mxd
            val     = new StringBuilder(16);                                           //mxd
            root    = InputStructure(ref data, ref pos, ref line, true);

            // Return true when done, false when errors occurred
            return(cpErrorResult == 0);
        }
Пример #13
0
        // This adds sectors
        private void WriteSectors(ICollection <Sector> sectors, UniversalParser textmap)
        {
            // Go for all sectors
            foreach (Sector s in sectors)
            {
                // Make collection
                UniversalCollection coll = new UniversalCollection();
                coll.Add("heightfloor", s.FloorHeight);
                coll.Add("heightceiling", s.CeilHeight);
                coll.Add("texturefloor", s.FloorTexture);
                coll.Add("textureceiling", s.CeilTexture);
                coll.Add("lightlevel", s.Brightness);
                if (s.Effect != 0)
                {
                    coll.Add("special", s.Effect);
                }
                if (s.Tag != 0)
                {
                    coll.Add("id", s.Tag);
                }

                // villsa 9/14/11 (builder64)
                coll.Add("color1", s.FloorColor.color.ToInt());
                coll.Add("color2", s.CeilColor.color.ToInt());
                coll.Add("color3", s.ThingColor.color.ToInt());
                coll.Add("color4", s.TopColor.color.ToInt());
                coll.Add("color5", s.LowerColor.color.ToInt());

                // villsa 9/13/11 - Flags
                foreach (KeyValuePair <string, bool> flag in s.Flags)
                {
                    if (flag.Value)
                    {
                        coll.Add(flag.Key, flag.Value);
                    }
                }

                coll.Comment = s.Index.ToString();

                // Add custom fields
                AddCustomFields(s, "sector", coll);

                // Store
                textmap.Root.Add("sector", coll);
            }
        }
        // This adds sidedefs
        private void WriteSidedefs(ICollection <Sidedef> sidedefs, UniversalParser textmap, IDictionary <Sector, int> sectorids)
        {
            // Go for all sidedefs
            foreach (Sidedef s in sidedefs)
            {
                // Make collection
                UniversalCollection coll = new UniversalCollection();
                if (s.OffsetX != 0)
                {
                    coll.Add("offsetx", s.OffsetX);
                }
                if (s.OffsetY != 0)
                {
                    coll.Add("offsety", s.OffsetY);
                }
                if (s.LongHighTexture != MapSet.EmptyLongName)
                {
                    coll.Add("texturetop", s.HighTexture);
                }
                if (s.LongLowTexture != MapSet.EmptyLongName)
                {
                    coll.Add("texturebottom", s.LowTexture);
                }
                if (s.LongMiddleTexture != MapSet.EmptyLongName)
                {
                    coll.Add("texturemiddle", s.MiddleTexture);
                }
                coll.Add("sector", sectorids[s.Sector]);
                coll.Comment = s.Index.ToString();

                //mxd. Flags
                foreach (KeyValuePair <string, bool> flag in s.Flags)
                {
                    if (flag.Value)
                    {
                        coll.Add(flag.Key, flag.Value);
                    }
                }

                // Add custom fields
                AddCustomFields(s, "sidedef", coll);

                // Store
                textmap.Root.Add("sidedef", coll);
            }
        }
Пример #15
0
        // This reads the vertices
        private Dictionary <int, Vertex> ReadVertices(MapSet map, UniversalParser textmap)
        {
            // Get list of entries
            List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "vertex");

            // Create lookup table
            Dictionary <int, Vertex> link = new Dictionary <int, Vertex>(collections.Count);

            // Go for all collections
            map.SetCapacity(map.Vertices.Count + collections.Count, 0, 0, 0, 0);
            for (int i = 0; i < collections.Count; i++)
            {
                // Read fields
                UniversalCollection c = collections[i];
                string where = "vertex " + i;
                float x = GetCollectionEntry(c, "x", true, 0.0f, where);
                float y = GetCollectionEntry(c, "y", true, 0.0f, where);

                // [ZZ] Correct location if it's NaN. Note that there cannot be any meaningful value here, so I just reset it to 0,0 to avoid triggering the NaN exception
                //      TODO: remove once the cause of NaN is reported
                if (float.IsNaN(x) || float.IsNaN(y))
                {
                    x = y = 0f;
                    General.ErrorLogger.Add(ErrorType.Warning, string.Format("Vertex {0} has NaN coordinates, resetting to 0,0", i));
                }

                // Create new item
                Vertex v = map.CreateVertex(new Vector2D(x, y));
                if (v != null)
                {
                    //mxd. zoffsets
                    v.ZCeiling = GetCollectionEntry(c, "zceiling", false, float.NaN, where);                 //mxd
                    v.ZFloor   = GetCollectionEntry(c, "zfloor", false, float.NaN, where);                   //mxd

                    // Custom fields
                    ReadCustomFields(c, v, "vertex");

                    // Add it to the lookup table
                    link.Add(i, v);
                }
            }

            // Return lookup table
            return(link);
        }
        // This adds vertices
        private void WriteVertices(ICollection <Vertex> vertices, UniversalParser textmap)
        {
            // Go for all vertices
            foreach (Vertex v in vertices)
            {
                // Make collection
                UniversalCollection coll = new UniversalCollection();
                coll.Add("x", v.Position.x);
                coll.Add("y", v.Position.y);
                coll.Comment = v.Index.ToString();

                // Add custom fields
                AddCustomFields(v, "vertex", coll);

                // Store
                textmap.Root.Add("vertex", coll);
            }
        }
        // This adds custom fields from a map element to a collection
        private void AddCustomFields(MapElement element, string elementname, UniversalCollection collection)
        {
            // Add custom fields
            foreach (KeyValuePair <string, UniValue> f in element.Fields)
            {
                // Not a managed field?
                if (!config.SettingExists("managedfields." + elementname + "." + f.Key))
                {
                    // Add type information to DBS file for map
                    if (remembercustomtypes)
                    {
                        General.Map.Options.SetUniversalFieldType(elementname, f.Key, f.Value.Type);
                    }

                    // Store field
                    collection.Add(f.Key, f.Value.Value);
                }
            }
        }
Пример #18
0
        // This reads the sectors
        private Dictionary <int, Sector> ReadSectors(MapSet map, UniversalParser textmap)
        {
            Dictionary <int, Sector> link;

            // Get list of entries
            List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector");

            // Create lookup table
            link = new Dictionary <int, Sector>(collections.Count);

            // Go for all collections
            map.SetCapacity(0, 0, 0, map.Sectors.Count + collections.Count, 0);
            for (int i = 0; i < collections.Count; i++)
            {
                // Read fields
                UniversalCollection c = collections[i];
                string where = "sector " + i;
                int    hfloor  = GetCollectionEntry <int>(c, "heightfloor", false, 0, where);
                int    hceil   = GetCollectionEntry <int>(c, "heightceiling", false, 0, where);
                string tfloor  = GetCollectionEntry <string>(c, "texturefloor", true, "-", where);
                string tceil   = GetCollectionEntry <string>(c, "textureceiling", true, "-", where);
                int    bright  = GetCollectionEntry <int>(c, "lightlevel", false, 160, where);
                int    special = GetCollectionEntry <int>(c, "special", false, 0, where);
                int    tag     = GetCollectionEntry <int>(c, "id", false, 0, where);

                // Create new item
                Sector s = map.CreateSector();
                if (s != null)
                {
                    s.Update(hfloor, hceil, tfloor, tceil, special, tag, bright);

                    // Custom fields
                    ReadCustomFields(c, s, "sector");

                    // Add it to the lookup table
                    link.Add(i, s);
                }
            }

            // Return lookup table
            return(link);
        }
Пример #19
0
        // This reads custom fields from a collection and adds them to a map element
        private void ReadCustomFields(UniversalCollection collection, MapElement element, string elementname)
        {
            element.Fields.BeforeFieldsChange();

            // Go for all the elements in the collection
            foreach (UniversalEntry e in collection)
            {
                // Check if not a managed field
                if (!config.SettingExists("managedfields." + elementname + "." + e.Key))
                {
                    int type = (int)UniversalType.Integer;

                    // Determine default type
                    if (e.Value.GetType() == typeof(int))
                    {
                        type = (int)UniversalType.Integer;
                    }
                    else if (e.Value.GetType() == typeof(float))
                    {
                        type = (int)UniversalType.Float;
                    }
                    else if (e.Value.GetType() == typeof(bool))
                    {
                        type = (int)UniversalType.Boolean;
                    }
                    else if (e.Value.GetType() == typeof(string))
                    {
                        type = (int)UniversalType.String;
                    }

                    // Try to find the type from configuration
                    if (setknowncustomtypes)
                    {
                        type = General.Map.Options.GetUniversalFieldType(elementname, e.Key, type);
                    }

                    // Make custom field
                    element.Fields[e.Key] = new UniValue(type, e.Value);
                }
            }
        }
        // This adds things
        private void WriteThings(ICollection <Thing> things, UniversalParser textmap)
        {
            // Go for all things
            foreach (Thing t in things)
            {
                // Make collection
                UniversalCollection coll = new UniversalCollection();
                if (t.Tag != 0)
                {
                    coll.Add("id", t.Tag);
                }
                coll.Add("x", t.Position.x);
                coll.Add("y", t.Position.y);
                if (t.Position.z != 0.0f)
                {
                    coll.Add("height", (float)t.Position.z);
                }
                coll.Add("angle", t.AngleDoom);
                coll.Add("type", t.Type);
                if (t.Action != 0)
                {
                    coll.Add("special", t.Action);
                }
                if (t.Args[0] != 0)
                {
                    coll.Add("arg0", t.Args[0]);
                }
                if (t.Args[1] != 0)
                {
                    coll.Add("arg1", t.Args[1]);
                }
                if (t.Args[2] != 0)
                {
                    coll.Add("arg2", t.Args[2]);
                }
                if (t.Args[3] != 0)
                {
                    coll.Add("arg3", t.Args[3]);
                }
                if (t.Args[4] != 0)
                {
                    coll.Add("arg4", t.Args[4]);
                }
                coll.Comment = t.Index.ToString();

                // Flags
                foreach (KeyValuePair <string, bool> flag in t.Flags)
                {
                    if (flag.Value)
                    {
                        coll.Add(flag.Key, flag.Value);
                    }
                }

                // Add custom fields
                AddCustomFields(t, "thing", coll);

                // Store
                textmap.Root.Add("thing", coll);
            }
        }
Пример #21
0
        // This writes the structures to a stream
        // NOTE: writenamespace may be null to omit writing the namespace to the stream.
        // NOTE: The given structures must be complete, with the exception of the sidedefs.
        // If there are missing sidedefs, their reference will be removed from the linedefs.
        public void Write(ICollection <Vertex> vertices, ICollection <Linedef> linedefs,
                          ICollection <Sidedef> sidedefs, ICollection <Sector> sectors,
                          ICollection <Thing> things, Stream stream, string writenamespace,
                          UniversalCollection unidentified = null)
        {
            UniversalParser textmap = new UniversalParser();

            // Begin with fields that must be at the top
            if (writenamespace != null)
            {
                textmap.Root.Add("namespace", writenamespace);
            }

            // ano - write unidentified fields to be preserved here
            if (unidentified != null)
            {
                foreach (UniversalEntry entry in unidentified)
                {
                    textmap.Root.Add(entry);
                }
            }


            Dictionary <Vertex, int>  vertexids  = new Dictionary <Vertex, int>();
            Dictionary <Sidedef, int> sidedefids = new Dictionary <Sidedef, int>();
            Dictionary <Sector, int>  sectorids  = new Dictionary <Sector, int>();

            // Index the elements in the data structures
            foreach (Vertex v in vertices)
            {
                vertexids.Add(v, vertexids.Count);
            }
            foreach (Sidedef sd in sidedefs)
            {
                sidedefids.Add(sd, sidedefids.Count);
            }
            foreach (Sector s in sectors)
            {
                sectorids.Add(s, sectorids.Count);
            }

            // If we write the custom field types again, then forget
            // all previous field types (this gets rid of unused field types)
            if (remembercustomtypes)
            {
                General.Map.Options.ForgetUniversalFieldTypes();
            }

            // Write the data structures to textmap
            WriteVertices(vertices, textmap);
            WriteLinedefs(linedefs, textmap, sidedefids, vertexids);
            WriteSidedefs(sidedefs, textmap, sectorids);
            WriteSectors(sectors, textmap);
            WriteThings(things, textmap);

            // Get the textmap as string
            string textmapstr = textmap.OutputConfiguration();

            // Write to stream
            StreamWriter writer = new StreamWriter(stream, Encoding.ASCII);

            writer.Write(textmapstr);
            writer.Flush();
        }
        // This adds linedefs
        private void WriteLinedefs(ICollection <Linedef> linedefs, UniversalParser textmap, IDictionary <Sidedef, int> sidedefids, IDictionary <Vertex, int> vertexids)
        {
            // Go for all linedefs
            foreach (Linedef l in linedefs)
            {
                // Make collection
                UniversalCollection coll = new UniversalCollection();
                if (l.Tag != 0)
                {
                    coll.Add("id", l.Tag);
                }
                coll.Add("v1", vertexids[l.Start]);
                coll.Add("v2", vertexids[l.End]);
                coll.Comment = l.Index.ToString();

                // Sidedef references
                if ((l.Front != null) && sidedefids.ContainsKey(l.Front))
                {
                    coll.Add("sidefront", sidedefids[l.Front]);
                }
                else
                {
                    coll.Add("sidefront", -1);
                }

                if ((l.Back != null) && sidedefids.ContainsKey(l.Back))
                {
                    coll.Add("sideback", sidedefids[l.Back]);
                }
                else
                {
                    coll.Add("sideback", -1);
                }

                // Special
                if (l.Action != 0)
                {
                    coll.Add("special", l.Action);
                }
                if (l.Args[0] != 0)
                {
                    coll.Add("arg0", l.Args[0]);
                }
                if (l.Args[1] != 0)
                {
                    coll.Add("arg1", l.Args[1]);
                }
                if (l.Args[2] != 0)
                {
                    coll.Add("arg2", l.Args[2]);
                }
                if (l.Args[3] != 0)
                {
                    coll.Add("arg3", l.Args[3]);
                }
                if (l.Args[4] != 0)
                {
                    coll.Add("arg4", l.Args[4]);
                }

                // Flags
                foreach (KeyValuePair <string, bool> flag in l.Flags)
                {
                    if (flag.Value)
                    {
                        coll.Add(flag.Key, flag.Value);
                    }
                }

                // Add custom fields
                AddCustomFields(l, "linedef", coll);

                // Store
                textmap.Root.Add("linedef", coll);
            }
        }
Пример #23
0
 // This creates a new configuration
 public void NewConfiguration()
 {
     // Create new configuration
     root = new UniversalCollection();
 }
Пример #24
0
        // This will create a data structure from the given object
        private string OutputStructure(UniversalCollection cs, int level, string newline, bool whitespace)
        {
            string        leveltabs = "";
            string        spacing   = "";
            StringBuilder db        = new StringBuilder("");

            // Check if this ConfigStruct is not empty
            if (cs.Count > 0)
            {
                // Create whitespace
                if (whitespace)
                {
                    for (int i = 0; i < level; i++)
                    {
                        leveltabs += "\t";
                    }
                    spacing = " ";
                }

                // Go for each item
                for (int i = 0; i < cs.Count; i++)
                {
                    // Check if the value if of collection type
                    if (cs[i].Value is UniversalCollection)
                    {
                        UniversalCollection c = (UniversalCollection)cs[i].Value;

                        // Output recursive structure
                        if (whitespace)
                        {
                            db.Append(leveltabs); db.Append(newline);
                        }
                        db.Append(leveltabs); db.Append(cs[i].Key);
                        if (!string.IsNullOrEmpty(c.Comment))
                        {
                            if (whitespace)
                            {
                                db.Append("\t");
                            }
                            db.Append("// " + c.Comment);
                        }
                        db.Append(newline);
                        db.Append(leveltabs); db.Append("{"); db.Append(newline);
                        db.Append(OutputStructure(c, level + 1, newline, whitespace));
                        db.Append(leveltabs); db.Append("}"); db.Append(newline);
                        //if(whitespace) { db.Append(leveltabs); db.Append(newline); } //mxd. Let's save a few Kbs by using single line breaks...
                    }
                    // Check if the value is of boolean type
                    else if (cs[i].Value is bool)
                    {
                        db.Append(leveltabs); db.Append(cs[i].Key); db.Append(spacing); db.Append("="); db.Append(spacing);
                        db.Append((bool)cs[i].Value ? "true;" : "false;"); db.Append(newline);
                    }
                    // Check if value is of float type
                    else if (cs[i].Value is float)
                    {
                        // Output the value as float (3 decimals)
                        float f = (float)cs[i].Value;
                        db.Append(leveltabs); db.Append(cs[i].Key); db.Append(spacing); db.Append("=");
                        db.Append(spacing); db.Append(f.ToString("0.000", CultureInfo.InvariantCulture)); db.Append(";"); db.Append(newline);
                    }
                    //mxd. Check if value is of double type
                    else if (cs[i].Value is double)
                    {
                        // Output the value as double (7 decimals)
                        double d = (double)cs[i].Value;
                        db.Append(leveltabs); db.Append(cs[i].Key); db.Append(spacing); db.Append("=");
                        db.Append(spacing); db.Append(d.ToString("0.0##############", CultureInfo.InvariantCulture)); /* db.Append(d.ToString("0.0000000", CultureInfo.InvariantCulture)); */ db.Append(";"); db.Append(newline);
                    }
                    // Check if value is of other numeric type
                    else if (cs[i].Value.GetType().IsPrimitive)
                    {
                        // Output the value unquoted
                        db.Append(leveltabs); db.Append(cs[i].Key); db.Append(spacing); db.Append("=");
                        db.Append(spacing); db.Append(String.Format(CultureInfo.InvariantCulture, "{0}", cs[i].Value)); db.Append(";"); db.Append(newline);
                    }
                    else
                    {
                        // Output the value with quotes and escape characters
                        db.Append(leveltabs); db.Append(cs[i].Key); db.Append(spacing); db.Append("=");
                        db.Append(spacing); db.Append("\""); db.Append(EscapedString(cs[i].Value.ToString())); db.Append("\";"); db.Append(newline);
                    }
                }
            }

            // Return the structure
            return(db.ToString());
        }
Пример #25
0
        // This parses a structure in the given data starting
        // from the given pos and line and updates pos and line.
        private UniversalCollection InputStructure(ref string[] data, ref int pos, ref int line, bool topLevel)
        {
            int pm = PM_NOTHING;                                // current parse mode

            key.Remove(0, key.Length);
            val.Remove(0, val.Length);
            bool escape            = false;                     // escape sequence?
            bool endofstruct       = false;                     // true as soon as this level struct ends
            UniversalCollection cs = new UniversalCollection();

            // Go through all of the data until
            // the end or until the struct closes
            // or when an arror occurred
            while ((cpErrorResult == 0) && (endofstruct == false))
            {
                // Get current character
                if (line == data.Length - 1)
                {
                    break;
                }
                if (pos > data[line].Length - 1)
                {
                    pos = 0;
                    line++;
                    if (string.IsNullOrEmpty(data[line]))
                    {
                        continue;                                                      //mxd. Skip empty lines here so correct line number is displayed on errors
                    }
                }

                char c = data[line][pos];                 // current data character

                // ================ What parse mode are we at?
                if (pm == PM_NOTHING)
                {
                    // Now check what character this is
                    switch (c)
                    {
                    case '{':                             // Begin of new struct
                        // Validate key
                        string s = key.ToString().Trim();
                        if (ValidateKey(s, line))
                        {
                            // Next character
                            pos++;

                            // Parse this struct and add it
                            cs.Add(new UniversalEntry(s.ToLowerInvariant(), InputStructure(ref data, ref pos, ref line, false)));

                            // Check the last character
                            pos--;

                            // Reset the key
                            key.Remove(0, key.Length);
                        }

                        // Leave switch
                        break;

                    case '}':                             // End of this struct
                        // Stop parsing in this struct
                        endofstruct = true;

                        // Leave the loop
                        break;

                    case '=':                             // Assignment
                        // Validate key
                        if (ValidateKey(key.ToString().Trim(), line))
                        {
                            // Now parsing assignment
                            pm = PM_ASSIGNMENT;
                        }

                        // Leave switch
                        break;

                    case ';':                             // Terminator

                        // Validate key
                        if (ValidateKey(key.ToString().Trim(), line))
                        {
                            // Error: No value
                            RaiseError(line, ERROR_KEYWITHOUTVALUE);
                        }

                        // Leave switch
                        break;

                    case '\n':                             // New line
                        // Count the line
                        line++;
                        pos = -1;

                        // Add this to the key as a space.
                        // Spaces are not allowed, but it will be trimmed
                        // when its the first or last character.
                        key.Append(" ");

                        // Leave switch
                        break;

                    case '\\':                             // Possible comment
                    case '/':
                        // Check for the line comment //
                        if (data[line].Substring(pos, 2) == "//")
                        {
                            // Skip everything on this line
                            pos = -1;

                            // Have next line?
                            if (line < data.Length - 1)
                            {
                                line++;
                            }
                        }
                        // Check for the block comment /* */
                        else if (data[line].Substring(pos, 2) == "/*")
                        {
                            // Block comment closes on the same line?.. (mxd)
                            int np = data[line].IndexOf("*/", pos);
                            if (np > -1)
                            {
                                pos = np + 1;
                            }
                            else
                            {
                                // Find the next closing block comment
                                line++;
                                while ((np = data[line].IndexOf("*/", 0)) == -1)
                                {
                                    if (line == data.Length - 1)
                                    {
                                        break;
                                    }
                                    line++;
                                }

                                // Closing block comment found?
                                if (np > -1)
                                {
                                    // Skip everything in this block
                                    pos = np + 1;
                                }
                            }
                        }

                        // Leave switch
                        break;

                    default:                             // Everything else
                        if (!topLevel && pos == 0)
                        {
                            while (matches.ContainsKey(data[line]))
                            {
                                cs.Add(matches[data[line]].Key, matches[data[line]].Value);
                                line++;
                                pos = -1;
                            }
                        }

                        // Add character to key
                        if (pos != -1)
                        {
                            key.Append(c);
                        }

                        // Leave switch
                        break;
                    }
                }
                // ================ Parsing an assignment
                else if (pm == PM_ASSIGNMENT)
                {
                    // Check for string opening
                    if (c == '\"')
                    {
                        // Now parsing string
                        pm = PM_STRING;                         //numbers
                    }
                    // Check for numeric character numbers
                    else if (Configuration.NUMBERS2.IndexOf(c) > -1)
                    {
                        // Now parsing number
                        pm = PM_NUMBER;

                        // Go one byte back, because this
                        // byte is part of the number!
                        pos--;
                    }
                    // Check for new line
                    else if (c == '\n')
                    {
                        // Count the new line
                        line++;
                    }
                    // Check if assignment ends
                    else if (c == ';')
                    {
                        // End of assignment
                        pm = PM_NOTHING;

                        // Remove this if it causes problems
                        key.Remove(0, key.Length);
                        val.Remove(0, val.Length);
                    }
                    // Otherwise (if not whitespace) it will be a keyword
                    else if ((c != ' ') && (c != '\t'))
                    {
                        // Now parsing a keyword
                        pm = PM_KEYWORD;

                        // Go one byte back, because this
                        // byte is part of the keyword!
                        pos--;
                    }
                }
                // ================ Parsing a number
                else if (pm == PM_NUMBER)
                {
                    // Check if number ends here
                    if (c == ';')
                    {
                        // Hexadecimal?
                        string s = val.ToString();
                        if ((s.Length > 2) && s.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                        {
                            // Convert to int
                            try
                            {
                                // Convert to value
                                int ival = Convert.ToInt32(s.Substring(2).Trim(), 16);

                                // Add it to struct
                                UniversalEntry entry = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), ival);
                                cs.Add(entry);
                                if (!matches.ContainsKey(data[line]))
                                {
                                    matches.Add(data[line], entry);
                                }
                            }
                            catch (OverflowException)
                            {
                                // Too large for Int32, try Int64
                                try
                                {
                                    // Convert to value
                                    long lval = Convert.ToInt64(s.Substring(2).Trim(), 16);

                                    // Add it to struct
                                    UniversalEntry entry = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), lval);
                                    cs.Add(entry);
                                    if (!matches.ContainsKey(data[line]))
                                    {
                                        matches.Add(data[line], entry);
                                    }
                                }
                                catch (OverflowException)
                                {
                                    // Too large for Int64, return error
                                    RaiseError(line, ERROR_VALUETOOBIG);
                                }
                                catch (FormatException)
                                {
                                    // ERROR: Invalid value in assignment
                                    RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\"");
                                }
                            }
                            catch (FormatException)
                            {
                                // ERROR: Invalid value in assignment
                                RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\"");
                            }
                        }
                        // Floating point?
                        //mxd. Can be in scientific notation (like "1E-06")
                        else if (s.IndexOf('.') > -1 || s.ToLowerInvariant().Contains("e-"))
                        {
                            double fval = 0;

                            // Convert to float (remove the f first)
                            try { fval = Convert.ToDouble(s.Trim(), CultureInfo.InvariantCulture); }
                            catch (FormatException)
                            {
                                // ERROR: Invalid value in assignment
                                RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\"");
                            }

                            // Add it to struct
                            UniversalEntry entry = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), fval);
                            cs.Add(entry);
                            if (!matches.ContainsKey(data[line]))
                            {
                                matches.Add(data[line], entry);
                            }
                        }
                        else
                        {
                            // Convert to int
                            try
                            {
                                // Convert to value
                                int ival = Convert.ToInt32(s.Trim(), CultureInfo.InvariantCulture);

                                // Add it to struct
                                UniversalEntry entry = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), ival);
                                cs.Add(entry);
                                if (!matches.ContainsKey(data[line]))
                                {
                                    matches.Add(data[line], entry);
                                }
                            }
                            catch (OverflowException)
                            {
                                // Too large for Int32, try Int64
                                try
                                {
                                    // Convert to value
                                    long lval = Convert.ToInt64(s.Trim(), CultureInfo.InvariantCulture);

                                    // Add it to struct
                                    UniversalEntry entry = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), lval);
                                    cs.Add(entry);
                                    if (!matches.ContainsKey(data[line]))
                                    {
                                        matches.Add(data[line], entry);
                                    }
                                }
                                catch (OverflowException)
                                {
                                    // Too large for Int64, return error
                                    RaiseError(line, ERROR_VALUETOOBIG);
                                }
                                catch (FormatException)
                                {
                                    // ERROR: Invalid value in assignment
                                    RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\"");
                                }
                            }
                            catch (FormatException)
                            {
                                // ERROR: Invalid value in assignment
                                RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\"");
                            }
                        }

                        // Reset key and value
                        key.Remove(0, key.Length);
                        val.Remove(0, val.Length);

                        // End of assignment
                        pm = PM_NOTHING;
                    }
                    // Check for new line
                    else if (c == '\n')
                    {
                        // Count the new line
                        line++;
                        pos = -1;
                    }
                    // Everything else is part of the value
                    else
                    {
                        val.Append(c);
                    }
                }
                // ================ Parsing a string
                else if (pm == PM_STRING)
                {
                    // Check if in an escape sequence
                    if (escape)
                    {
                        // What character?
                        switch (c)
                        {
                        case '\\': val.Append('\\'); break;

                        case 'n': val.Append(newline); break;

                        case '\"': val.Append('\"'); break;

                        case 'r': val.Append('\r'); break;

                        case 't': val.Append('\t'); break;

                        default:
                            // Is it a number?
                            if (Configuration.NUMBERS.IndexOf(c) > -1)
                            {
                                int  vv = 0;
                                char vc = '0';

                                // Convert the next 3 characters to a number
                                string v = data[line].Substring(pos, 3);
                                try { vv = Convert.ToInt32(v.Trim(), CultureInfo.InvariantCulture); }
                                catch (FormatException)
                                {
                                    // ERROR: Invalid value in assignment
                                    RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + v.Trim() + "\"");
                                }

                                // Convert the number to a char
                                try { vc = Convert.ToChar(vv, CultureInfo.InvariantCulture); }
                                catch (FormatException)
                                {
                                    // ERROR: Invalid value in assignment
                                    RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + v.Trim() + "\"");
                                }

                                // Add the char
                                val.Append(vc);
                            }
                            else
                            {
                                // Add the character as it is
                                val.Append(c);
                            }

                            // Leave switch
                            break;
                        }

                        // End of escape sequence
                        escape = false;
                    }
                    else
                    {
                        // Check for sequence start
                        if (c == '\\')
                        {
                            // Next character is of escape sequence
                            escape = true;
                        }
                        // Check if string ends
                        else if (c == '\"')
                        {
                            // Add string to struct
                            UniversalEntry entry = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), val.ToString());
                            cs.Add(entry);
                            if (!matches.ContainsKey(data[line]))
                            {
                                matches.Add(data[line], entry);
                            }

                            // End of assignment
                            pm = PM_ASSIGNMENT;

                            // Reset key and value
                            key.Remove(0, key.Length);
                            val.Remove(0, val.Length);
                        }
                        // Check for new line
                        else if (c == '\n')
                        {
                            // Count the new line
                            line++;
                            pos = -1;
                        }
                        // Everything else is just part of string
                        else
                        {
                            // Add to value
                            val.Append(c);
                        }
                    }
                }
                // ================ Parsing a keyword
                else if (pm == PM_KEYWORD)
                {
                    // Check if keyword ends
                    if (c == ';')
                    {
                        // Add to the struct depending on the keyword
                        switch (val.ToString().Trim().ToLowerInvariant())
                        {
                        case "true":
                            // Add boolean true
                            UniversalEntry t = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), true);
                            cs.Add(t);
                            if (!matches.ContainsKey(data[line]))
                            {
                                matches.Add(data[line], t);
                            }
                            break;

                        case "false":
                            // Add boolean false
                            UniversalEntry f = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), false);
                            cs.Add(f);
                            if (!matches.ContainsKey(data[line]))
                            {
                                matches.Add(data[line], f);
                            }
                            break;

                        case "nan":
                            // Add float value
                            UniversalEntry nan = new UniversalEntry(key.ToString().Trim().ToLowerInvariant(), double.NaN);
                            // Do not add NaN, just drop it with a warning
                            // cs.Add(nan);
                            warnings.Add("UDMF map data line " + (line + 1) + ": value of field " + key.ToString().Trim().ToLowerInvariant() + " has a value of NaN (not a number). Field is being dropped permanently.");
                            if (!matches.ContainsKey(data[line]))
                            {
                                matches.Add(data[line], nan);
                            }
                            break;

                        default:
                            // Unknown keyword
                            RaiseError(line, ERROR_KEYWORDUNKNOWN + "\n\nUnrecognized token: \"" + val.ToString().Trim() + "\"");
                            break;
                        }

                        // End of assignment
                        pm = PM_NOTHING;

                        // Reset key and value
                        key.Remove(0, key.Length);
                        val.Remove(0, val.Length);
                    }
                    // Check for new line
                    else if (c == '\n')
                    {
                        // Count the new line
                        line++;
                        pos = -1;
                    }
                    // Everything else is just part of keyword
                    else
                    {
                        // Add to value
                        val.Append(c);
                    }
                }

                // Next character
                pos++;
            }

            // Return the parsed result
            return(cs);
        }
Пример #26
0
        // This will create a data structure from the given object
        private string OutputStructure(UniversalCollection cs, int level, string newline, bool whitespace)
        {
            string        leveltabs = "";
            string        spacing   = "";
            StringBuilder db        = new StringBuilder("");

            // Check if this ConfigStruct is not empty
            if (cs.Count > 0)
            {
                // Create whitespace
                if (whitespace)
                {
                    for (int i = 0; i < level; i++)
                    {
                        leveltabs += "\t";
                    }
                    spacing = " ";
                }

                // Get enumerator
                IEnumerator <UniversalEntry> de = cs.GetEnumerator();

                // Go for each item
                for (int i = 0; i < cs.Count; i++)
                {
                    // Go to next item
                    de.MoveNext();

                    // Check if the value if of collection type
                    if (de.Current.Value is UniversalCollection)
                    {
                        UniversalCollection c = (UniversalCollection)de.Current.Value;

                        // Output recursive structure
                        if (whitespace)
                        {
                            db.Append(leveltabs); db.Append(newline);
                        }
                        db.Append(leveltabs); db.Append(de.Current.Key);
                        if (!string.IsNullOrEmpty(c.Comment))
                        {
                            if (whitespace)
                            {
                                db.Append("\t");
                            }
                            db.Append("//");
                            db.Append(c.Comment);
                        }
                        db.Append(newline);
                        db.Append(leveltabs); db.Append("{"); db.Append(newline);
                        db.Append(OutputStructure(c, level + 1, newline, whitespace));
                        db.Append(leveltabs); db.Append("}"); db.Append(newline);
                        if (whitespace)
                        {
                            db.Append(leveltabs); db.Append(newline);
                        }
                    }
                    // Check if the value is of boolean type
                    else if (de.Current.Value is bool)
                    {
                        // Check value
                        if ((bool)de.Current.Value == true)
                        {
                            // Output the keyword "true"
                            db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing);
                            db.Append("="); db.Append(spacing); db.Append("true;"); db.Append(newline);
                        }
                        else
                        {
                            // Output the keyword "false"
                            db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing);
                            db.Append("="); db.Append(spacing); db.Append("false;"); db.Append(newline);
                        }
                    }
                    // Check if value is of float type
                    else if (de.Current.Value is float)
                    {
                        // Output the value as float (3 decimals)
                        float f = (float)de.Current.Value;
                        db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing); db.Append("=");
                        db.Append(spacing); db.Append(f.ToString("0.000", CultureInfo.InvariantCulture)); db.Append(";"); db.Append(newline);
                    }
                    // Check if value is of other numeric type
                    else if (de.Current.Value.GetType().IsPrimitive)
                    {
                        // Output the value unquoted
                        db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing); db.Append("=");
                        db.Append(spacing); db.Append(String.Format(CultureInfo.InvariantCulture, "{0}", de.Current.Value)); db.Append(";"); db.Append(newline);
                    }
                    else
                    {
                        // Output the value with quotes and escape characters
                        db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing); db.Append("=");
                        db.Append(spacing); db.Append("\""); db.Append(EscapedString(de.Current.Value.ToString())); db.Append("\";"); db.Append(newline);
                    }
                }
            }

            // Return the structure
            return(db.ToString());
        }
Пример #27
0
        // This parses a structure in the given data starting
        // from the given pos and line and updates pos and line.
        private UniversalCollection InputStructure(ref string data, ref int pos, ref int line)
        {
            char c  = '\0';                                     // current data character
            int  pm = PM_NOTHING;                               // current parse mode
            //string key = "", val = "";		// current key and value beign built
            bool escape               = false;                  // escape sequence?
            bool endofstruct          = false;                  // true as soon as this level struct ends
            UniversalCollection cs    = new UniversalCollection();
            StringBuilder       keysb = new StringBuilder(32);
            StringBuilder       valsb = new StringBuilder(32);

            // Go through all of the data until
            // the end or until the struct closes
            // or when an arror occurred
            while ((pos < data.Length) && (cpErrorResult == 0) && (endofstruct == false))
            {
                // Get current character
                c = data[pos];

                // ================ What parse mode are we at?
                if (pm == PM_NOTHING)
                {
                    // Now check what character this is
                    switch (c)
                    {
                    case '{':                             // Begin of new struct

                        // Validate key
                    {
                        string key = keysb.ToString().Trim();
                        if (ValidateKey(key, line))
                        {
                            // Next character
                            pos++;

                            // Parse this struct and add it
                            cs.Add(new UniversalEntry(key, InputStructure(ref data, ref pos, ref line)));

                            // Check the last character
                            pos--;

                            // Reset the key
                            keysb.Length = 0;
                        }
                    }

                        // Leave switch
                        break;

                    case '}':                             // End of this struct

                        // Stop parsing in this struct
                        endofstruct = true;

                        // Leave the loop
                        break;

                    case '=':                             // Assignment

                        // Validate key
                        if (ValidateKey(keysb.ToString().Trim(), line))
                        {
                            // Now parsing assignment
                            pm = PM_ASSIGNMENT;
                        }

                        // Leave switch
                        break;

                    case ';':                             // Terminator

                        // Validate key
                        if (ValidateKey(keysb.ToString().Trim(), line))
                        {
                            // Error: No value
                            RaiseError(line, ERROR_KEYWITHOUTVALUE);
                        }

                        // Leave switch
                        break;

                    case '\n':                             // New line

                        // Count the line
                        line++;

                        // Add this to the key as a space.
                        // Spaces are not allowed, but it will be trimmed
                        // when its the first or last character.
                        keysb.Append(' ');

                        // Leave switch
                        break;

                    case '\\':                             // Possible comment
                    case '/':

                        // Check for the line comment //
                        if (data.Substring(pos, 2) == "//")
                        {
                            // Find the next line
                            int np = data.IndexOf("\n", pos);

                            // Next line found?
                            if (np > -1)
                            {
                                // Count the line
                                line++;

                                // Skip everything on this line
                                pos = np;
                            }
                            else
                            {
                                // No end of line
                                // Skip everything else
                                pos = data.Length;
                            }
                        }
                        // Check for the block comment /* */
                        else if (data.Substring(pos, 2) == "/*")
                        {
                            // Find the next closing block comment
                            int np = data.IndexOf("*/", pos);

                            // Closing block comment found?
                            if (np > -1)
                            {
                                // Count the lines in the block comment
                                string blockdata = data.Substring(pos, np - pos + 2);
                                line += (blockdata.Split("\n".ToCharArray()).Length - 1);

                                // Skip everything in this block
                                pos = np + 1;
                            }
                            else
                            {
                                // No end of line
                                // Skip everything else
                                pos = data.Length;
                            }
                        }

                        // Leave switch
                        break;

                    default:                             // Everything else

                        // Add character to key
                        keysb.Append(char.ToLowerInvariant(c));

                        // Leave switch
                        break;
                    }
                }
                // ================ Parsing an assignment
                else if (pm == PM_ASSIGNMENT)
                {
                    // Check for string opening
                    if (c == '\"')
                    {
                        // Now parsing string
                        pm = PM_STRING;
                    }
                    // Check for numeric character
                    //else if("0123456789-.&".IndexOf(c.ToString(CultureInfo.InvariantCulture)) > -1)
                    else if ((c >= '0' && c <= '9') || c == '&' || c == '-' || c == '.')
                    {
                        // Now parsing number
                        pm = PM_NUMBER;

                        // Go one byte back, because this
                        // byte is part of the number!
                        pos--;
                    }
                    // Check for new line
                    else if (c == '\n')
                    {
                        // Count the new line
                        line++;
                    }
                    // Check if assignment ends
                    else if (c == ';')
                    {
                        // End of assignment
                        pm = PM_NOTHING;

                        // Remove this if it causes problems
                        keysb.Length = 0;
                        valsb.Length = 0;
                    }
                    // Otherwise (if not whitespace) it will be a keyword
                    else if ((c != ' ') && (c != '\t'))
                    {
                        // Now parsing a keyword
                        pm = PM_KEYWORD;

                        // Go one byte back, because this
                        // byte is part of the keyword!
                        pos--;
                    }
                }
                // ================ Parsing a number
                else if (pm == PM_NUMBER)
                {
                    // Check if number ends here
                    if (c == ';')
                    {
                        string val = valsb.ToString().Trim();
                        string key = keysb.ToString().Trim();
                        // Hexadecimal?
                        if ((val.Length > 2) && val.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
                        {
                            int  ival = 0;
                            long lval = 0;

                            // Convert to int
                            try
                            {
                                // Convert to value
                                ival = System.Convert.ToInt32(val.Substring(2), 16);

                                // Add it to struct
                                cs.Add(new UniversalEntry(key, ival));
                            }
                            catch (System.OverflowException)
                            {
                                // Too large for Int32, try Int64
                                try
                                {
                                    // Convert to value
                                    lval = System.Convert.ToInt64(val.Substring(2), 16);

                                    // Add it to struct
                                    cs.Add(new UniversalEntry(key, lval));
                                }
                                catch (System.OverflowException)
                                {
                                    // Too large for Int64, return error
                                    RaiseError(line, ERROR_VALUETOOBIG);
                                }
                                catch (System.FormatException)
                                {
                                    // ERROR: Invalid value in assignment
                                    RaiseError(line, ERROR_VALUEINVALID);
                                }
                            }
                            catch (System.FormatException)
                            {
                                // ERROR: Invalid value in assignment
                                RaiseError(line, ERROR_VALUEINVALID);
                            }
                        }
                        // Floating point?
                        else if (val.IndexOf(".") > -1)
                        {
                            float fval = 0;

                            // Convert to float (remove the f first)
                            try { fval = System.Convert.ToSingle(val, CultureInfo.InvariantCulture); }
                            catch (System.FormatException)
                            {
                                // ERROR: Invalid value in assignment
                                RaiseError(line, ERROR_VALUEINVALID);
                            }

                            // Add it to struct
                            cs.Add(new UniversalEntry(key, fval));
                        }
                        else
                        {
                            int  ival = 0;
                            long lval = 0;

                            // Convert to int
                            try
                            {
                                // Convert to value
                                ival = System.Convert.ToInt32(val, CultureInfo.InvariantCulture);

                                // Add it to struct
                                cs.Add(new UniversalEntry(key, ival));
                            }
                            catch (System.OverflowException)
                            {
                                // Too large for Int32, try Int64
                                try
                                {
                                    // Convert to value
                                    lval = System.Convert.ToInt64(val, CultureInfo.InvariantCulture);

                                    // Add it to struct
                                    cs.Add(new UniversalEntry(key, lval));
                                }
                                catch (System.OverflowException)
                                {
                                    // Too large for Int64, return error
                                    RaiseError(line, ERROR_VALUETOOBIG);
                                }
                                catch (System.FormatException)
                                {
                                    // ERROR: Invalid value in assignment
                                    RaiseError(line, ERROR_VALUEINVALID);
                                }
                            }
                            catch (System.FormatException)
                            {
                                // ERROR: Invalid value in assignment
                                RaiseError(line, ERROR_VALUEINVALID);
                            }
                        }

                        // Reset key and value
                        keysb.Length = 0;
                        valsb.Length = 0;

                        // End of assignment
                        pm = PM_NOTHING;
                    }
                    // Check for new line
                    else if (c == '\n')
                    {
                        // Count the new line
                        line++;
                    }
                    // Everything else is part of the value
                    else
                    {
                        valsb.Append(char.ToLowerInvariant(c));
                    }
                }
                // ================ Parsing a string
                else if (pm == PM_STRING)
                {
                    // Check if in an escape sequence
                    if (escape)
                    {
                        // What character?
                        switch (c)
                        {
                        case '\\': valsb.Append('\\'); break;

                        case 'n': valsb.Append('\n'); break;

                        case '\"': valsb.Append('\"'); break;

                        case 'r': valsb.Append('\r'); break;

                        case 't': valsb.Append('\t'); break;

                        default:

                            // Is it a number?
                            //if("0123456789".IndexOf(c.ToString(CultureInfo.InvariantCulture)) > -1)
                            if (c >= '0' && c <= '9')
                            {
                                int  vv = 0;
                                char vc = '0';

                                // Convert the next 3 characters to a number
                                string v = data.Substring(pos, 3);
                                try { vv = System.Convert.ToInt32(v.Trim(), CultureInfo.InvariantCulture); }
                                catch (System.FormatException)
                                {
                                    // ERROR: Invalid value in assignment
                                    RaiseError(line, ERROR_VALUEINVALID);
                                }

                                // Convert the number to a char
                                try { vc = System.Convert.ToChar(vv, CultureInfo.InvariantCulture); }
                                catch (System.FormatException)
                                {
                                    // ERROR: Invalid value in assignment
                                    RaiseError(line, ERROR_VALUEINVALID);
                                }

                                // Add the char
                                valsb.Append(Char.ToLowerInvariant(vc));
                            }
                            else
                            {
                                // Add the character as it is
                                valsb.Append(c);
                            }

                            // Leave switch
                            break;
                        }

                        // End of escape sequence
                        escape = false;
                    }
                    else
                    {
                        // Check for sequence start
                        if (c == '\\')
                        {
                            // Next character is of escape sequence
                            escape = true;
                        }
                        // Check if string ends
                        else if (c == '\"')
                        {
                            // Add string to struct
                            cs.Add(new UniversalEntry(keysb.ToString().Trim(), valsb.ToString()));

                            // End of assignment
                            pm = PM_ASSIGNMENT;

                            // Reset key and value
                            keysb.Length = 0;
                            valsb.Length = 0;
                        }
                        // Check for new line
                        else if (c == '\n')
                        {
                            // Count the new line
                            line++;
                        }
                        // Everything else is just part of string
                        else
                        {
                            // Add to value
                            valsb.Append(c);
                        }
                    }
                }
                // ================ Parsing a keyword
                else if (pm == PM_KEYWORD)
                {
                    // Check if keyword ends
                    if (c == ';')
                    {
                        // Add to the struct depending on the keyword
                        switch (valsb.ToString().Trim().ToLowerInvariant())
                        {
                        case "true":

                            // Add boolean true
                            cs.Add(new UniversalEntry(keysb.ToString().Trim(), true));
                            break;

                        case "false":

                            // Add boolean false
                            cs.Add(new UniversalEntry(keysb.ToString().Trim(), false));
                            break;

                        default:

                            // Unknown keyword
                            RaiseError(line, ERROR_KEYWORDUNKNOWN);
                            break;
                        }

                        // End of assignment
                        pm = PM_NOTHING;

                        // Reset key and value
                        keysb.Length = 0;
                        valsb.Length = 0;
                    }
                    // Check for new line
                    else if (c == '\n')
                    {
                        // Count the new line
                        line++;
                    }
                    // Everything else is just part of keyword
                    else
                    {
                        // Add to value
                        valsb.Append(c);
                    }
                }

                // Next character
                pos++;
            }

            // Return the parsed result
            return(cs);
        }
Пример #28
0
        // This reads the linedefs and sidedefs
        private void ReadLinedefs(MapSet map, UniversalParser textmap,
                                  Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink)
        {
            // Get list of entries
            List <UniversalCollection> linescolls = GetNamedCollections(textmap.Root, "linedef");
            List <UniversalCollection> sidescolls = GetNamedCollections(textmap.Root, "sidedef");

            // Go for all lines
            map.SetCapacity(0, map.Linedefs.Count + linescolls.Count, map.Sidedefs.Count + sidescolls.Count, 0, 0);
            char[] splitter = { ' ' };             //mxd
            for (int i = 0; i < linescolls.Count; i++)
            {
                // Read fields
                UniversalCollection lc = linescolls[i];
                int[] args             = new int[Linedef.NUM_ARGS];
                string where = "linedef " + i;
                int v1 = GetCollectionEntry(lc, "v1", true, 0, where);
                int v2 = GetCollectionEntry(lc, "v2", true, 0, where);

                if (!vertexlink.ContainsKey(v1) || !vertexlink.ContainsKey(v2))
                {                 //mxd
                    General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed.");
                    continue;
                }

                int tag     = GetCollectionEntry(lc, "id", false, 0, where);
                int special = GetCollectionEntry(lc, "special", false, 0, where);
                args[0] = GetCollectionEntry(lc, "arg0", false, 0, where);
                args[1] = GetCollectionEntry(lc, "arg1", false, 0, where);
                args[2] = GetCollectionEntry(lc, "arg2", false, 0, where);
                args[3] = GetCollectionEntry(lc, "arg3", false, 0, where);
                args[4] = GetCollectionEntry(lc, "arg4", false, 0, where);
                int s1 = GetCollectionEntry(lc, "sidefront", false, -1, where);
                int s2 = GetCollectionEntry(lc, "sideback", false, -1, where);

                //mxd. MoreIDs
                List <int> tags = new List <int> {
                    tag
                };
                string moreids = GetCollectionEntry(lc, "moreids", false, string.Empty, where);
                if (!string.IsNullOrEmpty(moreids))
                {
                    string[] moreidscol = moreids.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string sid in moreidscol)
                    {
                        int id;
                        if (int.TryParse(sid.Trim(), out id) && id != 0 && !tags.Contains(id))
                        {
                            tags.Add(id);
                        }
                    }
                }
                if (tag == 0 && tags.Count > 1)
                {
                    tags.RemoveAt(0);
                }

                // Flags
                Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal);
                foreach (KeyValuePair <string, string> flag in General.Map.Config.LinedefFlags)
                {
                    stringflags[flag.Key] = GetCollectionEntry(lc, flag.Key, false, false, where);
                }
                foreach (FlagTranslation ft in General.Map.Config.LinedefFlagsTranslation)
                {
                    foreach (string field in ft.Fields)
                    {
                        stringflags[field] = GetCollectionEntry(lc, field, false, false, where);
                    }
                }

                // Activations
                foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
                {
                    stringflags[activate.Key] = GetCollectionEntry(lc, activate.Key, false, false, where);
                }

                // Check if not zero-length
                if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f)
                {
                    // Create new linedef
                    Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
                    if (l != null)
                    {
                        l.Update(stringflags, 0, tags, special, args);
                        l.UpdateCache();

                        // Custom fields
                        ReadCustomFields(lc, l, "linedef");

                        // Read sidedefs and connect them to the line
                        if (s1 > -1)
                        {
                            if (s1 < sidescolls.Count)
                            {
                                ReadSidedef(map, sidescolls[s1], l, true, sectorlink, s1);
                            }
                            else
                            {
                                General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed.");
                            }
                        }

                        if (s2 > -1)
                        {
                            if (s2 < sidescolls.Count)
                            {
                                ReadSidedef(map, sidescolls[s2], l, false, sectorlink, s2);
                            }
                            else
                            {
                                General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed.");
                            }
                        }
                    }
                }
                else
                {
                    General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed.");
                }
            }
        }
Пример #29
0
        // This reads custom fields from a collection and adds them to a map element
        private void ReadCustomFields(UniversalCollection collection, MapElement element, string elementname)
        {
            element.Fields.BeforeFieldsChange();

            // Go for all the elements in the collection
            foreach (UniversalEntry e in collection)
            {
                // mxd. Check if uifield
                if (uifields.ContainsKey(element.ElementType) && uifields[element.ElementType].ContainsKey(e.Key))
                {
                    int type = (int)uifields[element.ElementType][e.Key];

                    //mxd. Check type
                    object value = e.Value;

                    // Let's be kind and cast any int to a float if needed
                    if (type == (int)UniversalType.Float && e.Value is int)
                    {
                        value = (float)(int)e.Value;
                    }
                    else if (!e.IsValidType(e.Value.GetType()))
                    {
                        General.ErrorLogger.Add(ErrorType.Warning, element + ": the value of entry \"" + e.Key + "\" is of incompatible type (expected " + e.GetType().Name + ", but got " + e.Value.GetType().Name + "). If you save the map, this value will be ignored.");
                        continue;
                    }

                    // Make custom field
                    element.Fields[e.Key] = new UniValue(type, value);
                }                 // Check if not a managed field
                else if (!config.SettingExists("managedfields." + elementname + "." + e.Key))
                {
                    int type = (int)UniversalType.Integer;

                    //mxd. Try to find the type from configuration
                    if (setknowncustomtypes)
                    {
                        type = General.Map.Options.GetUniversalFieldType(elementname, e.Key, -1);

                        if (type != -1)
                        {
                            object value = e.Value;

                            // Let's be kind and cast any int to a float if needed
                            if (type == (int)UniversalType.Float && e.Value is int)
                            {
                                value = (float)(int)e.Value;
                            }
                            else if (!e.IsValidType(e.Value.GetType()))
                            {
                                General.ErrorLogger.Add(ErrorType.Warning, element + ": the value of entry \"" + e.Key + "\" is of incompatible type (expected " + e.GetType().Name + ", but got " + e.Value.GetType().Name + "). If you save the map, this value will be ignored.");
                                continue;
                            }

                            // Make custom field
                            element.Fields[e.Key] = new UniValue(type, value);
                            continue;
                        }
                    }

                    // Determine default type
                    if (e.Value is int)
                    {
                        type = (int)UniversalType.Integer;
                    }
                    else if (e.Value is float)
                    {
                        type = (int)UniversalType.Float;
                    }
                    else if (e.Value is bool)
                    {
                        type = (int)UniversalType.Boolean;
                    }
                    else if (e.Value is string)
                    {
                        type = (int)UniversalType.String;
                    }

                    // Make custom field
                    element.Fields[e.Key] = new UniValue(type, e.Value);
                }
            }
        }
Пример #30
0
        // This reads the sectors
        private Dictionary <int, Sector> ReadSectors(MapSet map, UniversalParser textmap)
        {
            // Get list of entries
            List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector");

            // Create lookup table
            Dictionary <int, Sector> link = new Dictionary <int, Sector>(collections.Count);

            // Go for all collections
            map.SetCapacity(0, 0, 0, map.Sectors.Count + collections.Count, 0);
            char[] splitter = new[] { ' ' };             //mxd
            for (int i = 0; i < collections.Count; i++)
            {
                // Read fields
                UniversalCollection c = collections[i];
                string where = "sector " + i;
                int    hfloor  = GetCollectionEntry(c, "heightfloor", false, 0, where);
                int    hceil   = GetCollectionEntry(c, "heightceiling", false, 0, where);
                string tfloor  = GetCollectionEntry(c, "texturefloor", true, "-", where);
                string tceil   = GetCollectionEntry(c, "textureceiling", true, "-", where);
                int    bright  = GetCollectionEntry(c, "lightlevel", false, 160, where);
                int    special = GetCollectionEntry(c, "special", false, 0, where);
                int    tag     = GetCollectionEntry(c, "id", false, 0, where);

                //mxd. MoreIDs
                List <int> tags = new List <int> {
                    tag
                };
                string moreids = GetCollectionEntry(c, "moreids", false, string.Empty, where);
                if (!string.IsNullOrEmpty(moreids))
                {
                    string[] moreidscol = moreids.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string sid in moreidscol)
                    {
                        int id;
                        if (int.TryParse(sid.Trim(), out id) && id != 0 && !tags.Contains(id))
                        {
                            tags.Add(id);
                        }
                    }
                }
                if (tag == 0 && tags.Count > 1)
                {
                    tags.RemoveAt(0);
                }

                //mxd. Read slopes
                float fslopex = GetCollectionEntry(c, "floorplane_a", false, 0.0f, where);
                float fslopey = GetCollectionEntry(c, "floorplane_b", false, 0.0f, where);
                float fslopez = GetCollectionEntry(c, "floorplane_c", false, 0.0f, where);
                float foffset = GetCollectionEntry(c, "floorplane_d", false, float.NaN, where);

                float cslopex = GetCollectionEntry(c, "ceilingplane_a", false, 0.0f, where);
                float cslopey = GetCollectionEntry(c, "ceilingplane_b", false, 0.0f, where);
                float cslopez = GetCollectionEntry(c, "ceilingplane_c", false, 0.0f, where);
                float coffset = GetCollectionEntry(c, "ceilingplane_d", false, float.NaN, where);

                //mxd. Read flags
                Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal);
                foreach (KeyValuePair <string, string> flag in General.Map.Config.SectorFlags)
                {
                    stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where);
                }
                foreach (KeyValuePair <string, string> flag in General.Map.Config.CeilingPortalFlags)
                {
                    stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where);
                }
                foreach (KeyValuePair <string, string> flag in General.Map.Config.FloorPortalFlags)
                {
                    stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where);
                }

                // Create new item
                Sector s = map.CreateSector();
                if (s != null)
                {
                    s.Update(hfloor, hceil, tfloor, tceil, special, stringflags, tags, bright, foffset, new Vector3D(fslopex, fslopey, fslopez).GetNormal(), coffset, new Vector3D(cslopex, cslopey, cslopez).GetNormal());

                    // Custom fields
                    ReadCustomFields(c, s, "sector");

                    // Add it to the lookup table
                    link.Add(i, s);
                }
            }

            // Return lookup table
            return(link);
        }