private static ModsInfo FilteVailedMod(ModsInfo mods)
        {
            ModsInfo result = default;

            foreach (var vaild_mod in (from mod in OPPAI_SUPPORT_MODS where mods.HasMod(mod) select mod))
            {
                result.Mod |= vaild_mod;
            }

            return(result);
        }
Beispiel #2
0
        public static void ParseBeatmap(ref byte[] beatmap_raw_data, Dictionary <string, string> extra_data, ModsInfo mods)
        {
            int    status = 0;
            double min_playable_start = double.MaxValue, max_playable_end = double.MinValue;
            int    nobjects = 0, ncircle = 0, nslider = 0, nspiner = 0;
            double min_bpm = int.MaxValue, max_bpm = int.MinValue, current_bpm = 0;

            using (StreamReader reader = new StreamReader(new MemoryStream(beatmap_raw_data)))
            {
                //简单的状态机
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine().Trim();

                    //[....]
                    if (line.StartsWith("[") && line.EndsWith("]") && status != 0)
                    {
                        status = 0;
                    }

                    switch (status)
                    {
                    case 0:     //seeking
                        if (line == "[General]")
                        {
                            status = 5;
                        }

                        if (line == "[Metadata]")
                        {
                            status = 1;
                        }

                        if (line == "[Difficulty]")
                        {
                            status = 4;
                        }

                        if (line == "[TimingPoints]")
                        {
                            status = 2;
                        }

                        if (line == "[HitObjects]")
                        {
                            status = 3;
                        }

                        break;

                    case 1:     //Metadata
                        if (string.IsNullOrWhiteSpace(line))
                        {
                            status = 0;
                            break;
                        }

                        foreach (var pair in METADATA_MAP)
                        {
                            if (line.StartsWith(pair.Key))
                            {
                                extra_data[pair.Value] = line.Remove(0, pair.Key.Length + 1).Trim();
                                break;
                            }
                        }

                        break;

                    case 5:     //General
                        if (string.IsNullOrWhiteSpace(line))
                        {
                            status = 0;
                            break;
                        }

                        foreach (var pair in GENERAL_MAP)
                        {
                            if (line.StartsWith(pair.Key))
                            {
                                extra_data[pair.Value] = line.Remove(0, pair.Key.Length + 1).Trim();
                                break;
                            }
                        }

                        break;

                    case 4:     //Difficulty
                        if (string.IsNullOrWhiteSpace(line))
                        {
                            status = 0;
                            break;
                        }

                        foreach (var pair in DIFFICALUT_MAP)
                        {
                            if (line.StartsWith(pair.Key))
                            {
                                extra_data[pair.Value] = line.Remove(0, pair.Key.Length + 1).Trim();
                                break;
                            }
                        }

                        break;

                    case 2:     //TimingPoints
                        if (string.IsNullOrWhiteSpace(line))
                        {
                            min_bpm = Math.Round(min_bpm, MidpointRounding.AwayFromZero);
                            max_bpm = Math.Round(max_bpm, MidpointRounding.AwayFromZero);

                            if (mods.HasMod(ModsInfo.Mods.DoubleTime) || mods.HasMod(ModsInfo.Mods.Nightcore))
                            {
                                min_bpm *= 1.5;
                                max_bpm *= 1.5;
                                min_bpm  = Math.Round(min_bpm, MidpointRounding.AwayFromZero);
                                max_bpm  = Math.Round(max_bpm, MidpointRounding.AwayFromZero);
                            }
                            if (mods.HasMod(ModsInfo.Mods.HalfTime))
                            {
                                min_bpm *= 0.75;
                                max_bpm *= 0.75;
                                min_bpm  = Math.Round(min_bpm, MidpointRounding.AwayFromZero);
                                max_bpm  = Math.Round(max_bpm, MidpointRounding.AwayFromZero);
                            }
#if DEBUG
                            Log.Debug($"[Oppai]BPM:{min_bpm} ~ {max_bpm}");
#endif

                            extra_data["min_bpm"] = min_bpm.ToString();
                            extra_data["max_bpm"] = max_bpm.ToString();

                            status = 0;
                            break;
                        }

                        bool     is_red_line = true;
                        string[] data        = line.Split(',');

                        if (data.Length >= 7)
                        {
                            if (data[6] == "1" || string.IsNullOrWhiteSpace(data[6]))
                            {
                                is_red_line = true;
                            }
                            else
                            {
                                is_red_line = false;
                            }
                        }

                        if (!is_red_line)
                        {
                            break;                  //1是红线
                        }
                        double val = double.Parse(data[1], CultureInfo.InvariantCulture);

                        if (val > 0)
                        {
                            val         = 60000 / val;
                            current_bpm = val;
                        }
                        else
                        {
                            double mul = Math.Abs(100 + val) / 100.0f;
                            val = current_bpm * (1 + mul);
                            break;
                        }

                        min_bpm = Math.Min(val, min_bpm);
                        max_bpm = Math.Max(val, max_bpm);
                        break;

                    case 3:
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            var obj_data = line.Split(',');

                            if (obj_data.Length >= 6)
                            {
                                double?time = null;

                                nobjects++;
                                int type = int.Parse(obj_data[3]);

                                if (IS_TYPE(type, TYPE_CIRCLE))
                                {
                                    ncircle++;
                                }
                                else if (IS_TYPE(type, TYPE_SLIDER))
                                {
                                    nslider++;
                                }
                                else if (IS_TYPE(type, TYPE_SPINER))
                                {
                                    nspiner++;
                                    time = double.Parse(obj_data[5]);
                                }
                                else if (IS_TYPE(type, TYPE_MANIA_HOLD))
                                {
                                    time = double.Parse(obj_data[4]);
                                }

                                var t = time ?? double.Parse(obj_data[2]);

                                min_playable_start = Math.Min(t, min_playable_start);
                                max_playable_end   = Math.Max(t, max_playable_end);
                            }
                        }
                        break;

                    default:
                        break;
                    }
                }
            }

            extra_data["num_objects"]  = nobjects.ToString();
            extra_data["num_circles"]  = ncircle.ToString();
            extra_data["num_sliders"]  = nslider.ToString();
            extra_data["num_spinners"] = nspiner.ToString();

            var playable_duration = (int)(max_playable_end /*- min_playable_start*/);//为什么Length直接拿最后一个物件来做的?
            extra_data["playable_duration"] = playable_duration.ToString();

            extra_data["playable_duration_min_part"] = (playable_duration / 1000 / 60).ToString();
            extra_data["playable_duration_sec_part"] = ((playable_duration / 1000) % 60).ToString();
        }