private void ReadNode(ref GbxParser parserd, qint32 classid, int pushdepth)
        {
            GbxClass dclass = new GbxClass();
            Classes.Add(pushdepth, dclass);
            dclass.Id = classid;
            switch (classid)
            {
                case unchecked((int)0x03043000):
                    dclass.Structure = new CGameCtnChallenge();
                    break;
                case unchecked((int)0x03093000):
                    dclass.Structure = new CGameCtnReplayRecord();
                    break;
                case unchecked((int)0x03059000):
                    dclass.Structure = new CGameCtnBlockSkin();
                    break;
                case unchecked((int)0x0313B000):
                    dclass.Structure = new CGameWaypointSpecialProperty();
                    break;
                default:
                    Debug.Log("Can not find a class struct..");
                    break;
            }

            // Parse data section

            while (true)
            {
                GbxChunk dchunk = new GbxChunk();
                oldcid = cid;
                cid = parserd.ReadInt32();
                dchunk.Id = cid;
                // Quit once we see this..
                if (cid == unchecked((int)0xFACADE01))
                    break;

                qint32 skip = parserd.ReadInt32();
                qint32 skipsize = -1;
                dchunk.Skipable = false;
                if (skip == 1397442896)
                {
                    skipsize = parserd.ReadInt32();
                    dchunk.Skipable = true;
                }
                else
                {
                    parserd.position -= 4;
                }
                qint32 start = parserd.position;
                switch (cid)
                {
                    // MAPS //
                    case unchecked((int)0x0304300D):
                        {
                            parserd.ReadStringLB();
                            parserd.ReadStringLB();
                            parserd.ReadStringLB();
                            break;
                        }
                    case unchecked((int)0x03043011):
                        {
                            // NodeReference
                            qint32 nodid = parserd.ReadInt32();
                            if (nodid >= 0 && !Classes.ContainsKey(nodid))
                            {
                                qint32 nodeclassid = parserd.ReadInt32();
                                ReadNode(ref parserd, nodeclassid, nodid);
                            }
                            // NodeReference
                            qint32 nodid2 = parserd.ReadInt32();
                            if (nodid2 >= 0 && !Classes.ContainsKey(nodid2))
                            {
                                qint32 nodeclassid = parserd.ReadInt32();
                                ReadNode(ref parserd, nodeclassid, nodid2);
                            }
                            parserd.ReadInt32();
                            break;
                        }
                    case unchecked((int)0x0301B000):
                        {
                            qint32 itemsct = parserd.ReadInt32();
                            for (int i = 0; i < itemsct; i++)
                            {
                                parserd.ReadStringLB();
                                parserd.ReadStringLB();
                                parserd.ReadStringLB();
                                parserd.ReadInt32();
                            }
                            break;

                        }
                    case unchecked((int)0x0305B000):
                        {
                            //    parserd.Skip(8*4);
                            break;
                        }
                    case unchecked((int)0x0305B001):
                        {
                            parserd.ReadString();
                            parserd.ReadString();
                            parserd.ReadString();
                            parserd.ReadString();
                            break;
                            //} case unchecked((int)0x0305B002): {
                            //} case unchecked((int)0x0305B003): {
                        }
                    case unchecked((int)0x0305B004):
                        {
                            parserd.Skip(5 * 4);
                            break;
                            //} case unchecked((int)0x0305B005): {
                            //} case unchecked((int)0x0305B006): {
                        }
                    case unchecked((int)0x0305B008):
                        {
                            parserd.Skip(2 * 4);
                            break;
                        }
                    case unchecked((int)0x0305B00A):
                        {
                            parserd.Skip(9 * 4);
                            break;
                        }
                    case unchecked((int)0x0305B00D):
                        {
                            parserd.Skip(1 * 4);
                            break;
                        }
                    case unchecked((int)0x0304301F):
                        {
                            // Blocks chunk
                            //if (parserd.position == 344) Debugger.Break();
                            //var pos = parserd.position;
                            var c = dclass.Structure;
                            c.MapUId = parserd.ReadStringLB();
                            c.Environment = parserd.ReadStringLB();
                            c.MapAuthor = parserd.ReadStringLB();
                            c.MapName = parserd.ReadString();
                            c.Mood = parserd.ReadStringLB();
                            c.EnvironmentBackground = parserd.ReadStringLB();
                            c.EnvironmentAuthor = parserd.ReadStringLB();

                            c.MapSizeX = parserd.ReadInt32();
                            c.MapSizeY = parserd.ReadInt32();
                            c.MapSizeZ = parserd.ReadInt32();
                            c.ReqUnlock = parserd.ReadInt32();
                            c.Flags32 = parserd.ReadInt32();
                            int numblocks = parserd.ReadInt32();
                            // Read every single block..
                            bool oneMore = false;
                            for (int i = 0; i < numblocks; i++)
                            {
                                MapBlock block = new MapBlock();
                                mapBlocks.Add(block);
                                block.BlockName = parserd.ReadStringLB();
                                block.Rotation = parserd.ReadByte();
                                block.PositionX = parserd.ReadByte();
                                block.PositionY = parserd.ReadByte();
                                block.PositionZ = parserd.ReadByte();
                                block.Flags = (c.Flags32 > 0) ? parserd.ReadUInt32() : parserd.ReadUInt16();
                                if (block.Flags != 0xFFFFFFFF)
                                    if ((block.Flags & 0x8000) != 0)
                                    {
                                        block.BlockSkinAuthor = parserd.ReadStringLB();
                                        // NodeReference
                                        block.BlockSkin = parserd.ReadInt32();
                                        if (block.BlockSkin >= 0 && !Classes.ContainsKey(block.BlockSkin)) // If not yet read..
                                        {
                                            qint32 cidd = parserd.ReadInt32();
                                            ReadNode(ref parserd, cidd, block.BlockSkin);
                                        }
                                    }
                                if (block.Flags != 0xFFFFFFFF && (block.Flags & 0x100000) != 0)
                                {
                                    // NodeReference
                                    block.BlockParams = parserd.ReadInt32();
                                    if (block.BlockParams >= 0 && !Classes.ContainsKey(block.BlockParams)) // If not yet read..
                                    {
                                        qint32 cidd = parserd.ReadInt32();
                                        ReadNode(ref parserd, cidd, block.BlockParams);
                                    }
                                }
                                c.Blocks.Add(block);
                                if (block.Flags == 0xFFFFFFFF)
                                    i -= 1;
                                if (oneMore)
                                    break;
                                if (i + 1 == numblocks) // We're at the latest block now, check if there could be an undefined block next...
                                {
                                    if (parserd.ReadInt32() == 10)
                                    {
                                        oneMore = true;
                                        i -= 1;
                                    }
                                    parserd.Skip(-4);
                                }
                            }
                            c.Trails = parserd.ReadBytes(12);
                            break;
                        } 
                    case unchecked((int)0x03043022):
                        {
                            parserd.ReadInt32();
                            break;
                        }
                    case unchecked((int)0x03043024):
                        {
                            var c = Classes[-1].Structure;
                            parserd.ReadChar();
                            parserd.Skip(32); // ?
                            c.PMapMusic = parserd.ReadString();
                            c.PMapMusicLoc = parserd.ReadString();
                            break;
                        }
                    case unchecked((int)0x03043025):
                        {
                            parserd.Skip(16); // 2x vec2d, float: 4 bytes
                            break;
                        }
                    case unchecked((int)0x03043026):
                        {
                            qint32 ind = parserd.ReadInt32();
                            if (ind >= 0 && !Classes.ContainsKey(ind))
                            {
                                qint32 cidd = parserd.ReadInt32();
                                ReadNode(ref parserd, cidd, ind);
                            }
                            break;
                        }
                    case unchecked((int)0x03043028):
                        {
                            qint32 p = parserd.ReadInt32();
                            if (p != 0)
                            {
                                parserd.Skip(1 + 4 * 3 * 3 + 4 * 3 + 4 + 4 + 4);
                            }
                            // Ugly temporarily fix, just to show it
                            CGameCtnChallenge_Header c = Classes[-2].Structure;
                            c.PMapComments = parserd.ReadString();
                            break;
                        }
                    case unchecked((int)0x0304302A):
                        {
                            parserd.ReadInt32();
                            break;
                        }
                    case unchecked((int)0x03043049):
                        {
                            // MT stuff
                            // No idea how to parse it so for now just read the rest
                            parserd.ReadBytes((int)(parserd.Length() - parserd.position - 4)); // the rest of the data - 4 (final unchecked((int)0xfacade01) )
                            //return;
                            break;
                        }
                    case unchecked((int)0x03043029):
                        {
                            var c = Classes[-1].Structure;
                            c.PMapPasswordHash = parserd.ReadBytes(16);
                            c.PMapPasswordCrc = parserd.ReadInt32();
                            break;
                        }
                    case unchecked((int)0x03059002):
                        {
                            dclass.StructureName = parserd.ReadString();
                            int version = parserd.ReadChar();
                            if (version != 3)
                                throw new Exception("Please re-save your map in the latest ManiaPlanet version in order to load the map in MapEdit.\nReason: FileReference version is outdated.");
                            parserd.Skip(32); // ?
                            QString a = parserd.ReadString();
                            dclass.Structure.Path = a;
                            //if (a.length() > 0)
                            dclass.Structure.PathLoc = parserd.ReadString();
                            parserd.ReadChar();
                            parserd.Skip(32); // ?
                            QString b = parserd.ReadString();
                            dclass.Structure.LocPath = b;
                            //if (b.length() > 0)
                            dclass.Structure.LocPathLoc = parserd.ReadString();
                            break;
                        }
                    case unchecked((int)0x0313B000):
                        {
                            dclass.Structure.Unknown = parserd.ReadInt32();
                            if (dclass.Structure.Unknown != 2)
                                throw new Exception("Please re-save your map in the latest ManiaPlanet version in order to load the map in MapEdit.\nReason: CGameWaypointSpecialProperty version is outdated.");
                            dclass.Structure.Tag = parserd.ReadString();
                            dclass.Structure.Order = parserd.ReadInt32();
                            break;

                            // REPLAYS //
                        }
                    case unchecked((int)0x03093002):
                        {
                            qint32 size = parserd.ReadInt32();
                            dclass.Structure.mapGbx = parserd.ReadBytes(size);
                            return; // Stop parsing after this part, replays are not fully parsed besides this.

                            // DEFAULT HANDLING //
                        }
                    default:
                        {
                            if (skipsize != -1)
                            {
                                parserd.Skip(skipsize);
                                cid = oldcid;
                            }
                            else
                            {
                                Debug.Log("Unknown chunk id 0x");
                                return; // temporarily
                            }
                            break;
                        }
                }
                dchunk.Data = parserd.GetChars(start, parserd.position - start);
                dclass.Chunks.Add(dchunk);
            }
        }
        private void ReadNode(ref GbxParser parserd, qint32 classid, int pushdepth)
        {
            GbxClass dclass = new GbxClass();

            Classes.Add(pushdepth, dclass);
            dclass.Id = classid;
            switch (classid)
            {
            case unchecked ((int)0x03043000):
                dclass.Structure = new CGameCtnChallenge();
                break;

            case unchecked ((int)0x03093000):
                dclass.Structure = new CGameCtnReplayRecord();
                break;

            case unchecked ((int)0x03059000):
                dclass.Structure = new CGameCtnBlockSkin();
                break;

            case unchecked ((int)0x0313B000):
                dclass.Structure = new CGameWaypointSpecialProperty();
                break;

            default:
                Debug.Log("Can not find a class struct..");
                break;
            }

            // Parse data section

            while (true)
            {
                GbxChunk dchunk = new GbxChunk();
                oldcid    = cid;
                cid       = parserd.ReadInt32();
                dchunk.Id = cid;
                // Quit once we see this..
                if (cid == unchecked ((int)0xFACADE01))
                {
                    break;
                }

                qint32 skip     = parserd.ReadInt32();
                qint32 skipsize = -1;
                dchunk.Skipable = false;
                if (skip == 1397442896)
                {
                    skipsize        = parserd.ReadInt32();
                    dchunk.Skipable = true;
                }
                else
                {
                    parserd.position -= 4;
                }
                qint32 start = parserd.position;
                switch (cid)
                {
                // MAPS //
                case unchecked ((int)0x0304300D):
                {
                    parserd.ReadStringLB();
                    parserd.ReadStringLB();
                    parserd.ReadStringLB();
                    break;
                }

                case unchecked ((int)0x03043011):
                {
                    // NodeReference
                    qint32 nodid = parserd.ReadInt32();
                    if (nodid >= 0 && !Classes.ContainsKey(nodid))
                    {
                        qint32 nodeclassid = parserd.ReadInt32();
                        ReadNode(ref parserd, nodeclassid, nodid);
                    }
                    // NodeReference
                    qint32 nodid2 = parserd.ReadInt32();
                    if (nodid2 >= 0 && !Classes.ContainsKey(nodid2))
                    {
                        qint32 nodeclassid = parserd.ReadInt32();
                        ReadNode(ref parserd, nodeclassid, nodid2);
                    }
                    parserd.ReadInt32();
                    break;
                }

                case unchecked ((int)0x0301B000):
                {
                    qint32 itemsct = parserd.ReadInt32();
                    for (int i = 0; i < itemsct; i++)
                    {
                        parserd.ReadStringLB();
                        parserd.ReadStringLB();
                        parserd.ReadStringLB();
                        parserd.ReadInt32();
                    }
                    break;
                }

                case unchecked ((int)0x0305B000):
                {
                    //    parserd.Skip(8*4);
                    break;
                }

                case unchecked ((int)0x0305B001):
                {
                    parserd.ReadString();
                    parserd.ReadString();
                    parserd.ReadString();
                    parserd.ReadString();
                    break;
                    //} case unchecked((int)0x0305B002): {
                    //} case unchecked((int)0x0305B003): {
                }

                case unchecked ((int)0x0305B004):
                {
                    parserd.Skip(5 * 4);
                    break;
                    //} case unchecked((int)0x0305B005): {
                    //} case unchecked((int)0x0305B006): {
                }

                case unchecked ((int)0x0305B008):
                {
                    parserd.Skip(2 * 4);
                    break;
                }

                case unchecked ((int)0x0305B00A):
                {
                    parserd.Skip(9 * 4);
                    break;
                }

                case unchecked ((int)0x0305B00D):
                {
                    parserd.Skip(1 * 4);
                    break;
                }

                case unchecked ((int)0x0304301F):
                {
                    // Blocks chunk
                    //if (parserd.position == 344) Debugger.Break();
                    //var pos = parserd.position;
                    var c = dclass.Structure;
                    c.MapUId                = parserd.ReadStringLB();
                    c.Environment           = parserd.ReadStringLB();
                    c.MapAuthor             = parserd.ReadStringLB();
                    c.MapName               = parserd.ReadString();
                    c.Mood                  = parserd.ReadStringLB();
                    c.EnvironmentBackground = parserd.ReadStringLB();
                    c.EnvironmentAuthor     = parserd.ReadStringLB();

                    c.MapSizeX  = parserd.ReadInt32();
                    c.MapSizeY  = parserd.ReadInt32();
                    c.MapSizeZ  = parserd.ReadInt32();
                    c.ReqUnlock = parserd.ReadInt32();
                    c.Flags32   = parserd.ReadInt32();
                    int numblocks = parserd.ReadInt32();
                    // Read every single block..
                    bool oneMore = false;
                    for (int i = 0; i < numblocks; i++)
                    {
                        MapBlock block = new MapBlock();
                        mapBlocks.Add(block);
                        block.BlockName = parserd.ReadStringLB();
                        block.Rotation  = parserd.ReadByte();
                        block.PositionX = parserd.ReadByte();
                        block.PositionY = parserd.ReadByte();
                        block.PositionZ = parserd.ReadByte();
                        block.Flags     = (c.Flags32 > 0) ? parserd.ReadUInt32() : parserd.ReadUInt16();
                        if (block.Flags != 0xFFFFFFFF)
                        {
                            if ((block.Flags & 0x8000) != 0)
                            {
                                block.BlockSkinAuthor = parserd.ReadStringLB();
                                // NodeReference
                                block.BlockSkin = parserd.ReadInt32();
                                if (block.BlockSkin >= 0 && !Classes.ContainsKey(block.BlockSkin))         // If not yet read..
                                {
                                    qint32 cidd = parserd.ReadInt32();
                                    ReadNode(ref parserd, cidd, block.BlockSkin);
                                }
                            }
                        }
                        if (block.Flags != 0xFFFFFFFF && (block.Flags & 0x100000) != 0)
                        {
                            // NodeReference
                            block.BlockParams = parserd.ReadInt32();
                            if (block.BlockParams >= 0 && !Classes.ContainsKey(block.BlockParams))         // If not yet read..
                            {
                                qint32 cidd = parserd.ReadInt32();
                                ReadNode(ref parserd, cidd, block.BlockParams);
                            }
                        }
                        c.Blocks.Add(block);
                        if (block.Flags == 0xFFFFFFFF)
                        {
                            i -= 1;
                        }
                        if (oneMore)
                        {
                            break;
                        }
                        if (i + 1 == numblocks)         // We're at the latest block now, check if there could be an undefined block next...
                        {
                            if (parserd.ReadInt32() == 10)
                            {
                                oneMore = true;
                                i      -= 1;
                            }
                            parserd.Skip(-4);
                        }
                    }
                    c.Trails = parserd.ReadBytes(12);
                    break;
                }

                case unchecked ((int)0x03043022):
                {
                    parserd.ReadInt32();
                    break;
                }

                case unchecked ((int)0x03043024):
                {
                    var c = Classes[-1].Structure;
                    parserd.ReadChar();
                    parserd.Skip(32);         // ?
                    c.PMapMusic    = parserd.ReadString();
                    c.PMapMusicLoc = parserd.ReadString();
                    break;
                }

                case unchecked ((int)0x03043025):
                {
                    parserd.Skip(16);         // 2x vec2d, float: 4 bytes
                    break;
                }

                case unchecked ((int)0x03043026):
                {
                    qint32 ind = parserd.ReadInt32();
                    if (ind >= 0 && !Classes.ContainsKey(ind))
                    {
                        qint32 cidd = parserd.ReadInt32();
                        ReadNode(ref parserd, cidd, ind);
                    }
                    break;
                }

                case unchecked ((int)0x03043028):
                {
                    qint32 p = parserd.ReadInt32();
                    if (p != 0)
                    {
                        parserd.Skip(1 + 4 * 3 * 3 + 4 * 3 + 4 + 4 + 4);
                    }
                    // Ugly temporarily fix, just to show it
                    CGameCtnChallenge_Header c = Classes[-2].Structure;
                    c.PMapComments = parserd.ReadString();
                    break;
                }

                case unchecked ((int)0x0304302A):
                {
                    parserd.ReadInt32();
                    break;
                }

                case unchecked ((int)0x03043049):
                {
                    // MT stuff
                    // No idea how to parse it so for now just read the rest
                    parserd.ReadBytes((int)(parserd.Length() - parserd.position - 4));         // the rest of the data - 4 (final unchecked((int)0xfacade01) )
                    //return;
                    break;
                }

                case unchecked ((int)0x03043029):
                {
                    var c = Classes[-1].Structure;
                    c.PMapPasswordHash = parserd.ReadBytes(16);
                    c.PMapPasswordCrc  = parserd.ReadInt32();
                    break;
                }

                case unchecked ((int)0x03059002):
                {
                    dclass.StructureName = parserd.ReadString();
                    int version = parserd.ReadChar();
                    if (version != 3)
                    {
                        throw new Exception("Please re-save your map in the latest ManiaPlanet version in order to load the map in MapEdit.\nReason: FileReference version is outdated.");
                    }
                    parserd.Skip(32);         // ?
                    QString a = parserd.ReadString();
                    dclass.Structure.Path = a;
                    //if (a.length() > 0)
                    dclass.Structure.PathLoc = parserd.ReadString();
                    parserd.ReadChar();
                    parserd.Skip(32);         // ?
                    QString b = parserd.ReadString();
                    dclass.Structure.LocPath = b;
                    //if (b.length() > 0)
                    dclass.Structure.LocPathLoc = parserd.ReadString();
                    break;
                }

                case unchecked ((int)0x0313B000):
                {
                    dclass.Structure.Unknown = parserd.ReadInt32();
                    if (dclass.Structure.Unknown != 2)
                    {
                        throw new Exception("Please re-save your map in the latest ManiaPlanet version in order to load the map in MapEdit.\nReason: CGameWaypointSpecialProperty version is outdated.");
                    }
                    dclass.Structure.Tag   = parserd.ReadString();
                    dclass.Structure.Order = parserd.ReadInt32();
                    break;

                    // REPLAYS //
                }

                case unchecked ((int)0x03093002):
                {
                    qint32 size = parserd.ReadInt32();
                    dclass.Structure.mapGbx = parserd.ReadBytes(size);
                    return;         // Stop parsing after this part, replays are not fully parsed besides this.

                    // DEFAULT HANDLING //
                }

                default:
                {
                    if (skipsize != -1)
                    {
                        parserd.Skip(skipsize);
                        cid = oldcid;
                    }
                    else
                    {
                        Debug.Log("Unknown chunk id 0x");
                        return;         // temporarily
                    }
                    break;
                }
                }
                dchunk.Data = parserd.GetChars(start, parserd.position - start);
                dclass.Chunks.Add(dchunk);
            }
        }