public override bool FromStream(Stream mstream, short ParsingRule, ThingDb.Thing thing)
        {
            NoxBinaryReader br = new NoxBinaryReader(mstream);
            // частота появления монстров
            int spawnRateNum = (int)br.ReadByte();

            MonsterSpawnRate = new byte[spawnRateNum];
            for (int i = 0; i < spawnRateNum; i++)
            {
                MonsterSpawnRate[i] = br.ReadByte();
            }
            // число уже созданных монстров
            SpawnedMonsters = br.ReadByte();
            // заменяется при загрузке на MonsterSpawnLimit
            SavedSpawnLimit = br.ReadByte();
            // должно быть 0 если карта не была сохранена игрой
            LastSpawnFrame = br.ReadUInt32();
            // скриптовые обработчики
            ScriptOnDamage  = br.ReadScriptEventString();
            ScriptOnDestroy = br.ReadScriptEventString();
            ScriptOnCollide = br.ReadScriptEventString();
            ScriptOnSpawn   = br.ReadScriptEventString();
            // монстры
            int           monsters      = (int)br.ReadByte();
            byte          spawnLimitNum = 0;
            List <string> monsterNames  = new List <string>(monsters);

            MonsterData = new byte[monsters][];
            for (int i = 0; i < monsters; i++)
            {
                // именно так
                if (!br.ReadBoolean())
                {
                    monsterNames.Add(null);
                    continue;
                }
                string monsterName = br.ReadString();
                short  unknown     = br.ReadInt16();            // увеличивается для следующего монстра
                // SkipToNextQword
                br.SkipToNextBoundary();
                long entryLenMB = br.ReadInt64();
                MonsterData[i] = br.ReadBytes((int)entryLenMB);

                /*
                 *      MonsterData - типичная инфа об обьекте
                 * short parsingRule1 = br.ReadInt16();
                 * short parsingRule2 = br.ReadInt16();
                 * br.ReadInt32(); // extent
                 * br.ReadInt32(); // globalID
                 * br.ReadSingle(); // X
                 * br.ReadSingle(); // Y
                 * byte term = br.ReadByte();
                 * result.MonsterData[i] = MonsterXfer.FromStream(br.BaseStream, ThingDb.Things[monsterName], parsingRule1);
                 */
                monsterNames.Add(monsterName);
            }
            spawnLimitNum = br.ReadByte();
            MonsterNames  = monsterNames.ToArray();
            // максимальное число создаваемых монстров, берется из gamedata.bin
            MonsterSpawnLimit = new byte[spawnLimitNum];
            for (int i = 0; i < spawnLimitNum; i++)
            {
                MonsterSpawnLimit[i] = br.ReadByte();
            }
            // настройки спавна: 0 - отключен, 1 - рандом позиция, 2 - зависит от игрока
            if (ParsingRule >= 63)
            {
                GenerationFlags = br.ReadInt32();
            }
            return(true);
        }
        public static MonsterGeneratorXfer FromStream(Stream mstream, short ParsingRule)
        {
            MonsterGeneratorXfer result = new MonsterGeneratorXfer();

            NoxBinaryReader br = new NoxBinaryReader(mstream);
            // частота появления монстров
            int spawnRateNum = (int) br.ReadByte();
            result.MonsterSpawnRate = new byte[spawnRateNum];
            for (int i = 0; i < spawnRateNum; i++)
                result.MonsterSpawnRate[i] = br.ReadByte();
            // число уже созданных монстров
            result.SpawnedMonsters = br.ReadByte();
            // заменяется при загрузке на MonsterSpawnLimit
            result.SavedSpawnLimit = br.ReadByte();
            // должно быть 0 если карта не была сохранена игрой
            result.LastSpawnFrame = br.ReadUInt32();
            // скриптовые обработчики
            result.ScriptOnDamage = br.ReadScriptEventString();
            result.ScriptOnDestroy = br.ReadScriptEventString();
            result.ScriptOnCollide = br.ReadScriptEventString();
            result.ScriptOnSpawn = br.ReadScriptEventString();
            // монстры
            int monsters = (int) br.ReadByte();
            byte spawnLimitNum = 0;
            List<string> monsterNames = new List<string>(monsters);
            result.MonsterData = new byte[monsters][];
            for (int i = 0; i < monsters; i++)
            {
                // именно так
                if (!br.ReadBoolean())
                {
                    monsterNames.Add(null);
                    continue;
                }
                string monsterName = br.ReadString();
                short unknown = br.ReadInt16(); // увеличивается для следующего монстра
                // SkipToNextQword
                br.SkipToNextBoundary();
                long entryLenMB = br.ReadInt64();
                result.MonsterData[i] = br.ReadBytes((int) entryLenMB);
                /*
              					MonsterData - типичная инфа об обьекте
                short parsingRule1 = br.ReadInt16();
                short parsingRule2 = br.ReadInt16();
                br.ReadInt32(); // extent
                br.ReadInt32(); // globalID
                br.ReadSingle(); // X
                br.ReadSingle(); // Y
                byte term = br.ReadByte();
                result.MonsterData[i] = MonsterXfer.FromStream(br.BaseStream, ThingDb.Things[monsterName], parsingRule1);
                */
                monsterNames.Add(monsterName);
            }
            spawnLimitNum = br.ReadByte();
            result.MonsterNames = monsterNames.ToArray();
            // максимальное число создаваемых монстров, берется из gamedata.bin
            result.MonsterSpawnLimit = new byte[spawnLimitNum];
            for (int i = 0; i < spawnLimitNum; i++)
                result.MonsterSpawnLimit[i] = br.ReadByte();
            // настройки спавна: 0 - отключен, 1 - рандом позиция, 2 - зависит от игрока
            if (ParsingRule >= 63)
                result.GenerationFlags = br.ReadInt32();
            return result;
        }