public void TestChangeSliderPath() { current.AddRange(new OsuHitObject[] { new HitCircle { StartTime = 1000 }, new Slider { StartTime = 2000, Path = new SliderPath(new[] { new PathControlPoint(Vector2.Zero), new PathControlPoint(Vector2.One), new PathControlPoint(new Vector2(2), PathType.Bezier), new PathControlPoint(new Vector2(3)), }, 50) }, new HitCircle { StartTime = 3000 }, }); var patch = new OsuBeatmap { HitObjects = { (OsuHitObject)current.HitObjects[0], new Slider { StartTime = 2000, Path = new SliderPath(new[] { new PathControlPoint(Vector2.Zero, PathType.Bezier), new PathControlPoint(new Vector2(4)), new PathControlPoint(new Vector2(5)), }, 100) }, (OsuHitObject)current.HitObjects[2], } }; runTest(patch); }
public void Reset(OsuBeatmap beatmap) { this.beatmap = beatmap; this.hitWindow50 = this.osuManager.HitWindow50((double)beatmap.OverallDifficulty); this.hitWindow100 = this.osuManager.HitWindow100((double)beatmap.OverallDifficulty); this.hitWindow300 = this.osuManager.HitWindow300((double)beatmap.OverallDifficulty); Mods currentMods = this.osuManager.Player.HitObjectManager.CurrentMods; this.audioRate = (currentMods.HasFlag(Mods.HalfTime) ? 0.75f : (currentMods.HasFlag(Mods.DoubleTime) ? 1.5f : 1f)); this.minOffset = this.calculateTimingOffset(this.configManager.HitTimingsMinOffset); this.maxOffset = this.calculateTimingOffset(this.configManager.HitTimingsMaxOffset); this.minAlternateOffset = this.calculateTimingOffset(this.configManager.HitTimingsAlternateMinOffset); this.maxAlternateOffset = this.calculateTimingOffset(this.configManager.HitTimingsAlternateMaxOffset); this.hitObjectRadius = this.osuManager.HitObjectRadius(beatmap.CircleSize); this.missRadius = (float)this.configManager.HitScanMissRadius; this.canMiss = false; this.lastHitScanIndex = -1; this.lastOnNotePosition = null; }
public void TestAddMultipleHitObjects() { current.AddRange(new[] { new HitCircle { StartTime = 1000, NewCombo = true }, new HitCircle { StartTime = 2000 }, new HitCircle { StartTime = 3000 }, }); var patch = new OsuBeatmap { HitObjects = { new HitCircle { StartTime = 500, NewCombo = true }, (OsuHitObject)current.HitObjects[0], new HitCircle { StartTime = 1500 }, (OsuHitObject)current.HitObjects[1], new HitCircle { StartTime = 2250 }, new HitCircle { StartTime = 2500 }, (OsuHitObject)current.HitObjects[2], new HitCircle { StartTime = 3500 }, } }; runTest(patch); }
public void TestDeleteMultipleHitObjects() { current.AddRange(new[] { new HitCircle { StartTime = 500 }, new HitCircle { StartTime = 1000 }, new HitCircle { StartTime = 1500 }, new HitCircle { StartTime = 2000 }, new HitCircle { StartTime = 2250 }, new HitCircle { StartTime = 2500 }, new HitCircle { StartTime = 3000 }, new HitCircle { StartTime = 3500 }, }); var patch = new OsuBeatmap { HitObjects = { (OsuHitObject)current.HitObjects[1], (OsuHitObject)current.HitObjects[3], (OsuHitObject)current.HitObjects[6], } }; runTest(patch); }
public async Task <string[]> GetBeatmap(string url) { if (noApi) { return(new string[] { url, url }); } string[] parts = url.Split('/'); int id = Convert.ToInt32(parts[parts.Length - 1]); bool isSet = parts[parts.Length - 2] == "s" ? true : false; OsuBeatmap[] maps = await m_client.GetBeatmap(id, isSet); if (maps.Length == 0) { return(new string[] { "404", "404" }); } OsuBeatmap map = maps[0]; string resp = ""; string respTwitch = ""; if (isSet) { resp = $"[{url} {map.artist} - {map.title}]"; respTwitch = $"{map.artist} - {map.title}"; } else { resp = $"[{url} {map.artist} - {map.title} [{map.version}]] by {map.creator} ({Math.Round(Convert.ToDouble(map.difficultyrating), 2)}*, CS{map.diff_size}, AR{map.diff_approach}, HP{map.diff_drain}, {map.bpm} BPM)"; respTwitch = $"{map.artist} - {map.title} [{map.version}] by {map.creator} ({Math.Round(Convert.ToDouble(map.difficultyrating), 2)}*, CS{map.diff_size}, AR{map.diff_approach}, HP{map.diff_drain}, {map.bpm} BPM)"; } await Task.FromResult(0); return(new string[] { resp, respTwitch }); }
public void TestChangeHitObjectAtSameTime() { current.AddRange(new[] { new HitCircle { StartTime = 500, Position = new Vector2(50) }, new HitCircle { StartTime = 500, Position = new Vector2(100) }, new HitCircle { StartTime = 500, Position = new Vector2(150) }, new HitCircle { StartTime = 500, Position = new Vector2(200) }, }); var patch = new OsuBeatmap { HitObjects = { new HitCircle { StartTime = 500, Position = new Vector2(150) }, new HitCircle { StartTime = 500, Position = new Vector2(100) }, new HitCircle { StartTime = 500, Position = new Vector2(50) }, new HitCircle { StartTime = 500, Position = new Vector2(200) }, } }; runTest(patch); }
public void Start(OsuBeatmap beatmap) { Ac__DisplayClass15_0 ac__DisplayClass15_ = default(Ac__DisplayClass15_0); ac__DisplayClass15_.A4__this = this; ac__DisplayClass15_.beatmap = beatmap; this.beatmap = ac__DisplayClass15_.beatmap; enabled = true; ac__DisplayClass15_.index = osu.Player.HitObjectManager.CurrentHitObjectIndex; ac__DisplayClass15_.currentHitObject = ac__DisplayClass15_.beatmap.HitObjects[ac__DisplayClass15_.index]; ac__DisplayClass15_.hitObjectRadius = osu.HitObjectRadius(ac__DisplayClass15_.beatmap.CircleSize); while (osu.CanPlay && ac__DisplayClass15_.index < ac__DisplayClass15_.beatmap.HitObjects.Count && enabled) { Thread.Sleep(10); if (osu.IsPaused) { continue; } int currentTime = osu.CurrentTime; if (currentTime <= ac__DisplayClass15_.currentHitObject.EndTime) { ac__DisplayClass15_.hitObjectPosition = ((ac__DisplayClass15_.currentHitObject is OsuSlider) ? (ac__DisplayClass15_.currentHitObject as OsuSlider).PositionAtTime(osu.CurrentTime) : ac__DisplayClass15_.currentHitObject.Position); if (!(ac__DisplayClass15_.currentHitObject is OsuSpinner)) { AStartg__aimAssist15_0(osu.WindowManager.PlayfieldToScreen(ac__DisplayClass15_.hitObjectPosition), ref ac__DisplayClass15_); } lastMousePos = osu.Player.Ruleset.MousePosition; } if (currentTime >= ac__DisplayClass15_.currentHitObject.EndTime) { AStartg__getNextObject15_2(ref ac__DisplayClass15_); } while (osu.CanPlay && ac__DisplayClass15_.index >= ac__DisplayClass15_.beatmap.HitObjects.Count && enabled) { Thread.Sleep(5); } } }
/// <summary> /// Get the specified score's accuracy. /// </summary> /// <param name="score">Play score.</param> /// <param name="beatmap">The same play's beatmap.</param> /// <returns></returns> public static double GetAccuracy(this IScore score, OsuBeatmap beatmap) { float accuracy = 0; var mapMode = beatmap.GameMode; float totalPointsOfHits; float totalNumberOfHits; // Logical switch for every mode if (mapMode == GameMode.Standard) { totalPointsOfHits = score.Count50 * 50 + score.Count100 * 100 + score.Count300 * 300; totalNumberOfHits = score.CountMiss + score.Count50 + score.Count100 + score.Count300; accuracy = totalPointsOfHits / (totalNumberOfHits * 300); } else if (mapMode == GameMode.Taiko) { totalPointsOfHits = (score.Count100 * 0.5f + score.Count300 * 1) * 300; totalNumberOfHits = score.CountMiss + score.Count100 + score.Count300; accuracy = totalPointsOfHits / (totalNumberOfHits * 300); } else if (mapMode == GameMode.CtB) { totalPointsOfHits = score.Count50 + score.Count100 + score.Count300; totalNumberOfHits = score.CountMiss + score.Count50 + score.Count100 + score.Count300 + score.CountKatu; accuracy = totalPointsOfHits / totalNumberOfHits; } else if (mapMode == GameMode.OsuMania) { totalPointsOfHits = score.Count50 * 50 + score.Count100 * 100 + score.CountKatu * 200 + (score.Count300 + score.CountGeki) * 300; totalNumberOfHits = score.CountMiss + score.Count50 + score.Count100 + score.CountKatu + score.Count300 + score.CountGeki; accuracy = totalPointsOfHits / (totalNumberOfHits * 300); } return(accuracy); }
public void Reset(OsuBeatmap beatmap) { this.beatmap = beatmap; hitWindow50 = osuManager.HitWindow50(beatmap.OverallDifficulty); hitWindow100 = osuManager.HitWindow100(beatmap.OverallDifficulty); hitWindow300 = osuManager.HitWindow300(beatmap.OverallDifficulty); var mods = osuManager.Player.HitObjectManager.CurrentMods; audioRate = mods.HasFlag(Mods.HalfTime) ? 0.75f : mods.HasFlag(Mods.DoubleTime) ? 1.5f : 1; minOffset = calculateTimingOffset(configManager.HitTimingsMinOffset); maxOffset = calculateTimingOffset(configManager.HitTimingsMaxOffset); minAlternateOffset = calculateTimingOffset(configManager.HitTimingsAlternateMinOffset); maxAlternateOffset = calculateTimingOffset(configManager.HitTimingsAlternateMaxOffset); hitObjectRadius = osuManager.HitObjectRadius(beatmap.CircleSize); missRadius = configManager.HitScanMissRadius; canMiss = false; lastHitScanIndex = -1; lastOnNotePosition = null; }
/// <summary> /// Loads the .qua, .osu or .sm file for a map. /// /// </summary> /// <returns></returns> /// <exception cref="ArgumentException"></exception> public Qua LoadQua(bool checkValidity = true) { // Reference to the parsed .qua file Qua qua; // Handle osu! maps as well switch (Game) { case MapGame.Quaver: var quaPath = $"{ConfigManager.SongDirectory}/{Directory}/{Path}"; qua = Qua.Parse(quaPath, checkValidity); break; case MapGame.Osu: var osu = new OsuBeatmap(MapManager.OsuSongsFolder + Directory + "/" + Path); qua = osu.ToQua(); break; default: throw new InvalidEnumArgumentException(); } return(qua); }
/// <summary> /// 使用OsuBeatmap初始化Beatmap对象 /// </summary> /// <param name="beatmap"></param> /// <param name="getStars"></param> public Beatmap(OsuBeatmap beatmap, bool getStars = true) { var info = new OsuInfo(); Title = beatmap.Title; TitleUnicode = beatmap.TitleUnicode; Artist = beatmap.Artist; ArtistUnicode = beatmap.ArtistUnicode; Creator = beatmap.Creator; Difficulty = beatmap.Difficulty; Version = Difficulty; FileName = beatmap.FileName; FullPath = Path.Combine(info.BeatmapDirectory, beatmap.FolderName, beatmap.FileName); DownloadLink = $"http://osu.ppy.sh/b/{beatmap.BeatmapId}"; Source = beatmap.Source; Tags = beatmap.Tags; Maker = ""; Md5 = new MD5String(beatmap.Md5); FullAudioFileName = Path.Combine(info.BeatmapDirectory, beatmap.FolderName, beatmap.AudioFileName); FullVideoFileName = ""; OverallDifficulty = beatmap.OverallDifficulty; HpDrain = beatmap.HpDrain; ApproachRate = beatmap.ApproachRate; CircleSize = beatmap.CircleSize; BeatmapSetId = beatmap.BeatmapSetId; AudioFileName = beatmap.AudioFileName; Mode = beatmap.Mode; if (getStars) { double.TryParse(beatmap.Stars.ToString(CultureInfo.InvariantCulture), out var stars); Stars = stars; } else { Stars = 0; } if (FullPath == "" || !File.Exists(FullPath)) { return; } var alllines = File.ReadAllLines(FullPath); if (!alllines[0].Contains("osu file format")) { NotValid = true; throw new InvalidBeatmapFileException($"文件{FullPath}不是谱面文件。"); } StringBuilder b = new StringBuilder(); foreach (var c in alllines[0]) { if (char.IsDigit(c)) { b.Append(c); } } BeatmapVersion = int.Parse(b.ToString()); foreach (var line in alllines) { var temparr = line.Split(':'); if (temparr[0].StartsWith("0,0,\"")) { if (string.IsNullOrEmpty(BackgroundFileName)) { BackgroundFileName = temparr[0].Split(',')[2].Replace("\"", "").Trim(); } FullBackgroundFileName = Path.Combine(BeatmapFolder, BackgroundFileName); continue; } if (temparr[0].StartsWith("Video,")) { VideoFileName = temparr[0].Split(',')[2].Replace("\"", "").Trim(); FullVideoFileName = Path.Combine(BeatmapFolder, FullVideoFileName); HasVideo = !string.IsNullOrEmpty(VideoFileName); continue; } FullVideoFileName = FullPath.Replace(FileName, VideoFileName); if (line.Contains("TimingPoints")) { break; } } BeatmapId = beatmap.BeatmapId; getAddtionalInfo(alllines); }
public void Run(ref Osu osu, ref OsuBeatmap beatmap) { // Check if correct beatmap is selected and is being played. if (beatmap == null || beatmap.Mode != BeatmapMode.Standard || !osu.IsMapPlaying()) { return; } int time = osu.GetAudioTime(); int hitObjectIndex = 0; BeatmapHitObject hitObject = beatmap.HitObjects[hitObjectIndex]; float hitObjectRadiusScaled = beatmap.HitObjectRadius * xMultiplier; float hitWindow300 = OsuGameRules.GetHitWindow300(beatmap.Difficulty.OverallDifficulty); float hitWindow100 = OsuGameRules.GetHitWindow100(beatmap.Difficulty.OverallDifficulty); float hitWindow50 = OsuGameRules.GetHitWindow50(beatmap.Difficulty.OverallDifficulty); // Can't even change the keys from UI. // 2017 programming LUL VirtualKeyCode primaryKey = VirtualKeyCode.VK_Z; VirtualKeyCode secondaryKey = VirtualKeyCode.VK_X; VirtualKeyCode allow100Key = VirtualKeyCode.SPACE; VirtualKeyCode activeKey = primaryKey; bool keyDown = false; // Default click window will simply be the timing offset. int clickWindow = Settings.Default.TimingOffset; float clickWindow300Min = -Math.Abs(hitWindow300) / 2.0f; float clickWindow300Max = Math.Abs(hitWindow300) / 2.0f; float clickWindow100Min = -Math.Abs(hitWindow100) / 1.5f; float clickWindow100Max = Math.Abs(hitWindow100) / 1.5f; // This needs tweaking for sure. Take into account if DT is enabled, otherwise it can hold active key for too long. float extraHoldTime = hitWindow300; float extraHoldTimeMin = extraHoldTime; float extraHoldTimeMax = extraHoldTime * 2.0f; float speedMultiplier = 1; if (Settings.Default.DoubleTime) { speedMultiplier = 1.5f; } else if (Settings.Default.HalfTime) { speedMultiplier = 0.75f; } float userSetBPM = Settings.Default.SingleTapMaxBPM / speedMultiplier / 2.0f; Random random = new Random(); while (hitObjectIndex <= beatmap.HitObjects.Capacity) { // Check if map is still playing. if (!osu.IsMapPlaying()) { break; } bool waiting = false; if (Settings.Default.HitScan && !hitObject.IsSpinner && !IsCursorOnCircle(GetScaledX(hitObject.X), GetScaledY(hitObject.Y), hitObjectRadiusScaled, Settings.Default.HitScanPixelOffset)) { waiting = true; } time = osu.GetAudioTime(); if (Settings.Default.RandomizeKeyTimings) { extraHoldTime = GetRandomNumber(random, extraHoldTimeMin, extraHoldTimeMax); if (InputSimulator.IsKeyDown(allow100Key)) { clickWindow = random.Next((int)clickWindow100Min, (int)clickWindow100Max) + Settings.Default.TimingOffset; } else { clickWindow = random.Next((int)clickWindow300Min, (int)clickWindow300Max) + Settings.Default.TimingOffset; } } float startTime = hitObject.StartTime + clickWindow; float endTime = hitObject.EndTime; // Only add extra hold time if the object is a circle OR it is a slider with hold time less than extra hold time. if (hitObject.IsCircle) { endTime += extraHoldTime; } else if (hitObject.IsSlider && (endTime - startTime) < extraHoldTime) { endTime = startTime + extraHoldTime; } if (time >= startTime && !keyDown && !waiting) { if (Settings.Default.TappingStyle == 1 && !hitObject.IsSpinner && (hitObjectIndex + 1) <= beatmap.HitObjects.Count) // Single, not a spinner and next hit object exists. { BeatmapHitObject nextHitObject = beatmap.HitObjects[hitObjectIndex + 1]; int nextObjectBPM = beatmap.MsPerBeatToBPM(nextHitObject.StartTime - hitObject.EndTime); int userSetBPMFinal = (int)Math.Round(userSetBPM * beatmap.GetTimingPointFromOffset(time).Meter); if (nextObjectBPM > userSetBPMFinal) { activeKey = (activeKey == primaryKey) ? secondaryKey : primaryKey; } else { activeKey = primaryKey; } } // Hold active key. InputSimulator.SimulateKeyDown(activeKey); keyDown = true; } else if (time > endTime && keyDown) { // Release active key. InputSimulator.SimulateKeyUp(activeKey); keyDown = false; if (Settings.Default.TappingStyle == 0) // Alternate { activeKey = (activeKey == primaryKey) ? secondaryKey : primaryKey; } // Advance to the next hit object. hitObjectIndex++; hitObject = beatmap.HitObjects[hitObjectIndex]; } // Can't get a 50 anymore, move on to the next object. else if (waiting && time > (hitObject.EndTime + hitWindow50)) { hitObjectIndex++; hitObject = beatmap.HitObjects[hitObjectIndex]; } // Release keys if game is paused to prevent accidentaly hitting a menu button. if (!osu.IsAudioPlaying() && keyDown) { InputSimulator.SimulateKeyUp(activeKey); } Task.Delay(1).Wait(); } // Make sure keys are released when done. if (keyDown) { InputSimulator.SimulateKeyUp(activeKey); } }
private OsuBeatmap ReadBeatmap() { var osustars = new Dictionary <int, double>(); var taikostars = new Dictionary <int, double>(); var ctbstars = new Dictionary <int, double>(); var maniastars = new Dictionary <int, double>(); if (Manifest.Version < 20191106) { //谱面条目的大小 //The size of the entry of the beatmap in byte GetInt32(); } var beatmap = new OsuBeatmap { //曲目的作者 //Artist of the audio of the beatmap Artist = GetString(), //曲目作者的原语言 //"Artist" in native language ArtistUnicode = GetString(), //谱面的标题 //Title of the beatmap Title = GetString(), //谱面标题的原语言 //"Title" in native language TitleUnicode = GetString(), //谱面的作者 //Author of the beatmap Creator = GetString(), //谱面的难度 //Difficulty of beatmap Difficulty = GetString(), //谱面音频文件的名字,可能指示不存在的文件 //The audio file name of the beatmap. Not existing file may be indicated. AudioFileName = GetString(), //谱面的Md5 //Md5 hash of the beatmap Md5 = GetString(), //谱面文件的名称 //The name of beatmap file FileName = GetString() }; try { //谱面的状态(Ranked,Loved,Pending等) //Status of beatmap like Ranked, Loved, Pending, etc. beatmap.BeatmapStatus = (OsuBeatmapStatus)Enum.Parse(typeof(OsuBeatmapStatus), GetByte().ToString()); } catch { //谱面状态读取失败时为未知状态 //The unknown will be assigned when failed to read beatmap.BeatmapStatus = OsuBeatmapStatus.Unknown; } //圈圈的数量 //The number of HitCircle beatmap.HitCircle = GetInt16(); //滑条的数量 //The number of slider beatmap.Slider = GetInt16(); //转盘的数量 //The number of spinners. beatmap.Spinner = GetInt16(); //谱面上一次修改的时间,单位为Tick //The time when the last modification of the beatmap in Ticks beatmap.LastModificationTime = new DateTime(GetInt64()); //谱面的缩圈速度 //The speed of the narrow of the approaching circle beatmap.ApproachRate = GetSingle(); //谱面的圈圈的大小 //The size of the notes of the beatmap beatmap.CircleSize = GetSingle(); //谱面游玩时掉血的速度和回血的难度 //The speed of HP reducing and the difficulty of HP raising beatmap.HpDrain = GetSingle(); //谱面的综合难度(如判定难度) //Overall difficulty of beatmap like HitWindow. beatmap.OverallDifficulty = GetSingle(); //滑条速度 //Slider velocity GetDouble(); if (Manifest.Version >= 20140609) { //获取std模式的Mod<->难度星级的键值对 //Get the key-value pairs of Mod and Stars in std mode GetModStarsPair(_binReader, osustars, GetInt32()); //获取Taiko模式的Mod<->难度星级的键值对 //Get the key-value pairs of Mod and Stars in Taiko mode GetModStarsPair(_binReader, taikostars, GetInt32()); //获取CTB模式的Mod<->难度星级的键值对 //Get the key-value pairs of Mod and Stars in CTB mode GetModStarsPair(_binReader, ctbstars, GetInt32()); //获取Mania模式的Mod<->难度星级的键值对 //Get the key-value pairs of Mod and Stars in Mania mode GetModStarsPair(_binReader, maniastars, GetInt32()); } //谱面最后一个打击物件的偏移 //The offset of the last HitObject beatmap.DrainTime = TimeSpan.FromSeconds(GetInt32()); //谱面的总长度 //The total time of beatmap beatmap.TotalTime = TimeSpan.FromMilliseconds(GetInt32()); //谱面预览点的偏移 //The offset of the preview point beatmap.PreviewPoint = TimeSpan.FromMilliseconds(GetInt32()); //获取谱面OsuTimingPoint //Get the OsuTimingPoints of the beatmap. GetTimingPoints(_binReader, beatmap.TimingPoints, GetInt32()); //谱面的Id //Id of the beatmap beatmap.BeatmapId = GetInt32(); //谱面集的Id //Id of beatmap set beatmap.BeatmapSetId = GetInt32(); //谱面的帖子Id //The id of the thread of the beatmap beatmap.ThreadId = GetInt32(); //谱面在std模式的通过数 //Grade achieved at the beatmap in std mode GetByte(); //谱面在Taiko模式的通过数 //Grade achieved at the beatmap in Taiko mode GetByte(); //谱面在CTB模式的通过数 //Grade achieved at the beatmap in CTB mode GetByte(); //谱面在Mania模式的通过数 //Grade achieved at the beatmap in Mania mode GetByte(); //本地的谱面偏移 //Local beatmap offset GetInt16(); //堆叠系数 //Stack leniency GetSingle(); //游戏模式 //Game mode beatmap.Mode = (OsuGameMode)GetByte(); if (osustars.Count == 0) { osustars.Add(0, 0); } if (taikostars.Count == 0) { taikostars.Add(0, 0); } if (ctbstars.Count == 0) { ctbstars.Add(0, 0); } if (maniastars.Count == 0) { maniastars.Add(0, 0); } beatmap.ModStarPair.SetModeDict(OsuGameMode.Osu, osustars); beatmap.ModStarPair.SetModeDict(OsuGameMode.Taiko, taikostars); beatmap.ModStarPair.SetModeDict(OsuGameMode.Catch, ctbstars); beatmap.ModStarPair.SetModeDict(OsuGameMode.Mania, maniastars); //谱面曲目的来源 //The source of the audio of the beatmap beatmap.Source = GetString(); //谱面的标签 //The tags of the beatmap beatmap.Tags = GetString(); //在线存储的偏移量 //The offset stored at online GetInt16(); //歌曲标题使用的字体 //The font used for the title of the beatmap GetString(); //这个谱面是否没玩过 //Is the beatmap unplayed GetBoolean(); //谱面上次的游玩时间 //Last time when the beatmap played GetInt64(); //谱面是否为osz2 //Is the beatmap osz2 GetBoolean(); //谱面所在的文件夹名 //The folder name that the beatmap in beatmap.FolderName = GetString(); //谱面上次与osu!仓库核对时的时间 //Last time when beatmap was checked against osu! repository GetInt64(); //是否不使用谱面的音效 //Are the sounds of the beatmap ignored GetBoolean(); //是否不使用谱面的皮肤 //Is the skin of the beatmap ignored GetBoolean(); //是否禁用了StoryBoard //Is the StoryBoard of the beatmap disabled GetBoolean(); //是否禁用了视频 //Is the vedio of the beatmap disabled GetBoolean(); //是否改动可视化设置 //If visual overrided GetBoolean(); if (Manifest.Version < 20140609) { //未知用途,可能不存在 //Unknown usage. May be null GetInt16(); } //疑为上次修改时间 //May be last modification time GetInt32(); //Mania的下落速度 //Scrolling speed of mania mode GetByte(); try { beatmap.Stars = beatmap.ModStarPair[beatmap.Mode][0]; } catch { beatmap.Stars = 0; Debug.WriteLine("Error when reading stars return beatmap with 0 star."); return(beatmap); } return(beatmap); }
/// <summary> /// Exports the entire mapset to a zip (.qp) file. /// </summary> public void ExportToZip() { var exportsDir = $"{ConfigManager.DataDirectory}/Exports/"; System.IO.Directory.CreateDirectory(exportsDir); var tempFolder = $"{ConfigManager.DataDirectory}/temp/{GameBase.Game.TimeRunning}/"; System.IO.Directory.CreateDirectory(tempFolder); using (var archive = ZipArchive.Create()) { foreach (var map in Maps) { try { switch (map.Game) { case MapGame.Quaver: var path = $"{ConfigManager.SongDirectory.Value}/{map.Directory}/{map.Path}"; File.Copy(path, $"{tempFolder}/{map.Path}"); break; // Map is from osu!, so we need to convert it to .qua format case MapGame.Osu: var osuPath = $"{MapManager.OsuSongsFolder}{map.Directory}/{map.Path}"; var osu = new OsuBeatmap(osuPath); map.BackgroundPath = osu.Background; var name = StringHelper.FileNameSafeString($"{map.Artist} - {map.Title} [{map.DifficultyName}].qua"); var savePath = $"{tempFolder}/{name}"; osu.ToQua().Save(savePath); Logger.Debug($"Successfully converted osu beatmap: {osuPath}", LogType.Runtime); break; } // Copy over audio file if necessary if (File.Exists(MapManager.GetAudioPath(map)) && !File.Exists($"{tempFolder}/{map.AudioPath}")) { File.Copy(MapManager.GetAudioPath(map), $"{tempFolder}/{map.AudioPath}"); } // Copy over background file if necessary if (File.Exists(MapManager.GetBackgroundPath(map)) && !File.Exists($"{tempFolder}/{map.BackgroundPath}")) { File.Copy(MapManager.GetBackgroundPath(map), $"{tempFolder}/{map.BackgroundPath}"); } } catch (Exception e) { Logger.Error(e, LogType.Runtime); } } archive.AddAllFromDirectory(tempFolder); var outputPath = exportsDir + $"{StringHelper.FileNameSafeString(Artist + " - " + Title + " - " + GameBase.Game.TimeRunning)}.qp"; archive.SaveTo(outputPath, CompressionType.Deflate); Utils.NativeUtils.HighlightInFileManager(outputPath); } System.IO.Directory.Delete(tempFolder, true); }
public void Start(OsuBeatmap beatmap) { this.beatmap = beatmap; shouldStop = false; hitWindow50 = osuManager.HitWindow50(beatmap.OverallDifficulty); leftClick = (VirtualKeyCode)osuManager.BindingManager.GetKeyCode(Bindings.OsuLeft); rightClick = (VirtualKeyCode)osuManager.BindingManager.GetKeyCode(Bindings.OsuRight); accuracyManager.Reset(beatmap); bool isHit = false; int hitTime = 0; int index = osuManager.Player.HitObjectManager.CurrentHitObjectIndex; OsuHitObject currentHitObject = beatmap.HitObjects[index]; var alternateResult = AlternateResult.None; OsuKeys currentKey = configManager.PrimaryKey; HitObjectTimings currentHitTimings = accuracyManager.GetHitObjectTimings(index, false, false); while (osuManager.CanPlay && index < beatmap.HitObjects.Count && !shouldStop) { Thread.Sleep(1); if (osuManager.IsPaused) { if (isHit) { isHit = false; releaseAllKeys(); } continue; } int currentTime = osuManager.CurrentTime + configManager.AudioOffset; if (currentTime >= currentHitObject.StartTime - hitWindow50) { if (!isHit) { var hitScanResult = accuracyManager.GetHitScanResult(index); switch (hitScanResult) { case HitScanResult.CanHit when currentTime >= currentHitObject.StartTime + currentHitTimings.StartOffset: case HitScanResult.ShouldHit: { isHit = true; hitTime = currentTime; if (configManager.PlayStyle == PlayStyles.TapX && alternateResult == AlternateResult.None) { inputSimulator.Mouse.LeftButtonDown(); currentKey = configManager.PrimaryKey; } else if (currentKey == OsuKeys.K1 || currentKey == OsuKeys.K2) { inputSimulator.Keyboard.KeyDown(currentKey == OsuKeys.K1 ? leftClick : rightClick); } else if (currentKey == OsuKeys.M1) { inputSimulator.Mouse.LeftButtonDown(); } else { inputSimulator.Mouse.RightButtonDown(); } } break; case HitScanResult.MoveToNextObject: moveToNextObject(); break; } } else if (currentTime >= (currentHitObject is OsuHitCircle ? hitTime : currentHitObject.EndTime) + currentHitTimings.HoldTime) { moveToNextObject(); if (currentHitObject is OsuSpinner && currentHitObject.StartTime - beatmap.HitObjects[index - 1].EndTime <= configManager.HoldBeforeSpinnerTime) { continue; } isHit = false; releaseAllKeys(); } } } releaseAllKeys(); while (osuManager.CanPlay && index >= beatmap.HitObjects.Count && !shouldStop) { Thread.Sleep(5); } void moveToNextObject() { index++; if (index < beatmap.HitObjects.Count) { currentHitObject = beatmap.HitObjects[index]; alternateResult = getAlternateResult(index); if (alternateResult.HasFlag(AlternateResult.AlternateThisNote)) { currentKey = currentKey == configManager.PrimaryKey ? configManager.SecondaryKey : configManager.PrimaryKey; } else { currentKey = configManager.PrimaryKey; } currentHitTimings = accuracyManager.GetHitObjectTimings(index, alternateResult.HasFlag(AlternateResult.AlternateThisNote), inputSimulator.InputDeviceState.IsKeyDown(configManager.DoubleDelayKey)); } } }
/// <summary> /// Converts a .osz archive file to .qua format. M /// (Makes it available to play in Quaver) /// </summary> public static void ConvertOsz(string file, string extractDirectory) { var time = (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Milliseconds; var tempFolder = $@"{ConfigManager.DataDirectory}/Temp/{Path.GetFileNameWithoutExtension(file)} - {time}"; if (Directory.Exists(tempFolder)) { Directory.Delete(tempFolder, true); } Directory.CreateDirectory(tempFolder); try { // Extract the .osz archive to the temporary folder using (var archive = ArchiveFactory.Open(file)) { foreach (var entry in archive.Entries) { if (!entry.IsDirectory) { entry.WriteToDirectory(tempFolder, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true }); } } } // Convert all .osu files in the temp folder to .qua foreach (var osuFile in Directory.GetFiles(tempFolder, "*.osu", SearchOption.AllDirectories)) { try { var map = new OsuBeatmap(osuFile); if (!map.IsValid) { continue; } // Convert the map to .qua map.ToQua().Save(map.OriginalFileName.Replace(".osu", ".qua")); } catch (Exception e) { Logger.Error(e, LogType.Runtime); } } Directory.CreateDirectory(extractDirectory); // Go through each file in the temp folder and add it to the target directory foreach (var tempFile in Directory.GetFiles(tempFolder)) { var fileName = $"{extractDirectory}/{Path.GetFileName(tempFile)}"; // Make sure the path to the file is less than 200 characters while (fileName.Length > 200) { fileName = fileName.Remove(fileName.Length - 1); } // Go through each file and move it. switch (Path.GetExtension(tempFile).ToLower()) { case ".qua": case ".mp3": case ".jpg": case ".png": case ".jpeg": case ".ogg": File.Move(tempFile, fileName); break; default: continue; } } } catch (Exception e) { Logger.Error(e, LogType.Runtime); } }
public void Start(OsuBeatmap beatmap) { Ac__DisplayClass18_0 ac__DisplayClass18_ = default(Ac__DisplayClass18_0); ac__DisplayClass18_.A4__this = this; ac__DisplayClass18_.beatmap = beatmap; this.beatmap = ac__DisplayClass18_.beatmap; enabled = true; ac__DisplayClass18_.key1 = (VirtualKeyCode)osu.BindingManager.GetKeyCode(Bindings.OsuLeft); ac__DisplayClass18_.key2 = (VirtualKeyCode)osu.BindingManager.GetKeyCode(Bindings.OsuRight); currentKeyPressed = ac__DisplayClass18_.key2; ac__DisplayClass18_.beatmapSpeed = (osu.Player.HitObjectManager.CurrentMods.HasFlag(Mods.DoubleTime) ? 1.5f : (osu.Player.HitObjectManager.CurrentMods.HasFlag(Mods.HalfTime) ? 0.75f : 1f)); int num = osu.HitWindow50(ac__DisplayClass18_.beatmap.OverallDifficulty); int num2 = osu.HitWindow50(ac__DisplayClass18_.beatmap.OverallDifficulty); int num3 = osu.HitWindow100(ac__DisplayClass18_.beatmap.OverallDifficulty); int num4 = osu.HitWindow300(ac__DisplayClass18_.beatmap.OverallDifficulty); ac__DisplayClass18_.hitObjectRadius = osu.HitObjectRadius(ac__DisplayClass18_.beatmap.CircleSize); ac__DisplayClass18_.alreadyHit = false; bool flag = false; ac__DisplayClass18_.rand = new Random(); ac__DisplayClass18_.randomOffset = ac__DisplayClass18_.rand.Next(-offset, offset); ac__DisplayClass18_.randomHoldTime = ac__DisplayClass18_.rand.Next((int)(((float)holdTime - 5f) * ac__DisplayClass18_.beatmapSpeed), (int)(((float)holdTime + 5f) * ac__DisplayClass18_.beatmapSpeed)); ac__DisplayClass18_.lastTimeHit = 0; ac__DisplayClass18_.index = osu.Player.HitObjectManager.CurrentHitObjectIndex; ac__DisplayClass18_.currentHitObject = ac__DisplayClass18_.beatmap.HitObjects[ac__DisplayClass18_.index]; AStartg__releaseBothKeys18_2(ref ac__DisplayClass18_); Ac__DisplayClass18_1 ac__DisplayClass18_2 = default(Ac__DisplayClass18_1); while (osu.CanPlay && ac__DisplayClass18_.index < ac__DisplayClass18_.beatmap.HitObjects.Count && enabled) { TimingHelper.Delay(1u); if (osu.IsPaused) { Thread.Sleep(5); continue; } ac__DisplayClass18_2.currentTime = osu.CurrentTime; if (ac__DisplayClass18_2.currentTime >= ac__DisplayClass18_.currentHitObject.StartTime - num) { ac__DisplayClass18_.hitObjectPosition = ((ac__DisplayClass18_.currentHitObject is OsuSlider) ? (ac__DisplayClass18_.currentHitObject as OsuSlider).PositionAtTime(osu.CurrentTime) : ac__DisplayClass18_.currentHitObject.Position); if (!ac__DisplayClass18_.alreadyHit) { if (AStartg__isMouseOnNote18_1(ref ac__DisplayClass18_)) { if (ac__DisplayClass18_2.currentTime >= ac__DisplayClass18_.currentHitObject.StartTime + ac__DisplayClass18_.randomOffset) { flag = false; AStartg__pressKey18_4(ref ac__DisplayClass18_, ref ac__DisplayClass18_2); } } else if (ac__DisplayClass18_2.currentTime >= ac__DisplayClass18_.currentHitObject.StartTime + num2) { flag = true; AStartg__pressKey18_4(ref ac__DisplayClass18_, ref ac__DisplayClass18_2); } } } if (!flag & ac__DisplayClass18_.alreadyHit) { if (ac__DisplayClass18_2.currentTime >= ac__DisplayClass18_.currentHitObject.EndTime + ac__DisplayClass18_.randomOffset + ac__DisplayClass18_.randomHoldTime) { AStartg__releaseKey18_5(ref ac__DisplayClass18_); AStartg__getNextObject18_3(ref ac__DisplayClass18_); } } else if (ac__DisplayClass18_2.currentTime >= ac__DisplayClass18_.currentHitObject.EndTime + num2 + ac__DisplayClass18_.randomHoldTime) { AStartg__releaseKey18_5(ref ac__DisplayClass18_); AStartg__getNextObject18_3(ref ac__DisplayClass18_); } while (osu.CanPlay && ac__DisplayClass18_.index >= ac__DisplayClass18_.beatmap.HitObjects.Count && enabled) { Thread.Sleep(5); } } }
public void SuccessfulParse() { var converter = new OsuBeatmap(BeatmapFilename); Assert.True(converter.IsValid); }
public void FailUponBadPath() { var converter = new OsuBeatmap("bad-path-no-file"); Assert.False(converter.IsValid); }
public async Task GetRecent([Remainder] string target = null) { SocketUserMessage msg = await Context.Channel.SendMessageAsync("Fetching data...", attachID : true); ulong?targetID = null; string username = string.Empty; string country = string.Empty; OsuGameModes gameMode = OsuGameModes.STD; if (string.IsNullOrEmpty(target)) { OsuBoundUserDB bound = await OsuDB.GetBoundUserBy_DiscordID(Context.Message.Author.ID); if (bound != null) { targetID = bound.UserID; country = bound.Country; username = bound.UserName; gameMode = bound.MainMode; } else { await msg.EditAsync($"You were not found in the database.\n" + $"To use this command without parameters, proceed to bind your profile with `$osubind [username]`", null); } } else { if (target.Where(x => x < '0' || x > '9').Count() > 0) { //Not ID } else { targetID = ulong.Parse(target); } } OsuUserRecent recent = await OsuNetwork.DownloadUserRecent(targetID.Value, gameMode); OsuBeatmap beatmap = await OsuNetwork.DownloadBeatmap(recent.BeatmapID, gameMode); if (beatmap == null) { await msg.EditAsync("", null); } else { OsuUser beatmapCreator = await OsuNetwork.DownloadUser(beatmap.Creator, gameMode); EmbedBuilder eb = beatmap.ToEmbedBuilder(gameMode, beatmapCreator, true); eb.Fields.Insert(0, new EmbedFieldBuilder { Name = $"Recent {CustomEmoji.Osu.Gamemode.GetGamemodeEmoji(gameMode)}", Value = recent.ToScoreString(country, gameMode, username, nameFormat: '\u200b') }); await msg.EditAsync("", eb.Build()); } }
public async Task GetBeatmapPack(string ID) { SocketUserMessage msg = await Context.Channel.SendMessageAsync("Fetching data...", attachID : true); IEnumerable <OsuBeatmap> beatmapPack = await OsuNetwork.DownloadBeatmapPack(int.Parse(ID), logger : msg); beatmapPack = beatmapPack.OrderBy(x => x.Difficulty.Rating).OrderBy(x => x.GameMode); OsuGameModes[] gameModes; //get amount of gamemodes present in the beatmapset { List <OsuGameModes> collector = new List <OsuGameModes>(); Tool.ForEach(beatmapPack, x => { if (!collector.Contains(x.GameMode)) { collector.Add(x.GameMode); } }); gameModes = collector.ToArray(); } OsuBeatmap packRef = beatmapPack.First(); OsuUser creator = await OsuNetwork.DownloadUser(packRef.Creator, OsuGameModes.STD, tolerateNull : true, maxAttempts : 3); EmbedBuilder eb = new EmbedBuilder(); eb.WithAuthor(x => { x.Name = packRef.Title; x.Url = packRef.URL; x.IconUrl = "https://cdn.discordapp.com/attachments/420948614966411299/421301562032390164/beatmapPackLogo.png"; }); eb.Image = $"{packRef.CoverPictureURL}"; //$"https://b.ppy.sh/thumb/{packRef.BeatmapSetID}l.jpg"; eb.Description = ""; if (creator != null) { eb.Description += $"Created By: [{creator.Username}]({creator.ProfileURL})\n"; } eb.Description += $"📥 **[Download]({packRef.DownloadURL(false)})**"; eb.Color = Color.FromArgb(28, 164, 185); eb.Thumbnail = packRef.ThumbnailPictureURL; eb.Footer = packRef.GetFooter(creator); eb.AddField(x => { x.Name = $"{packRef.Length} ⏱ {packRef.FavouriteCount} ❤️"; x.Value = $"BPM: **{string.Format("{0:0.##}", packRef.BPM)}**"; }); //Display beatmaps { void addBeatmapField(OsuGameModes gamemode, bool includeName) { eb.AddField(x => { x.Name = includeName ? $"{CustomEmoji.Osu.Gamemode.GetGamemodeEmoji(gamemode)} {OsuGameModesConverter.GameModeName(gamemode)}" : CustomEmoji.Void.ToString(); x.Value = "empty"; x.IsInline = true; }); } for (int i = 0; i < gameModes.Length; i++) { for (int ii = 0; ii < 2; ii++) { addBeatmapField(gameModes[i], ii == 0); } } OsuGameModes previousMode = OsuGameModes.None; int efbRef = 0; int efbPos = -1; foreach (OsuBeatmap beatmap in beatmapPack) { if (previousMode != beatmap.GameMode) { previousMode = beatmap.GameMode; efbPos++; efbRef = 0; } string beatmapVersion = beatmap.Version; if (beatmapVersion.Length > 14) { beatmapVersion = beatmapVersion.Substring(0, 14) + "..."; } string beatmapInfo = $"{CustomEmoji.Osu.Difficulty.GetDifficultyEmoji(beatmap.Difficulty.Rating, beatmap.GameMode)} **[{beatmapVersion}](https://osu.ppy.sh/b/{beatmap.BeatmapID})**\n"; // - *{string.Format("{0:0.##}", beatmap.Difficulty.Rating)}★* if (eb.Fields[efbPos * 2 + efbRef + 1].Value == "empty") { eb.Fields[efbPos * 2 + efbRef + 1].Value = beatmapInfo; } else { eb.Fields[efbPos * 2 + efbRef + 1].Value += beatmapInfo; } efbRef++; if (efbRef == 2) { efbRef = 0; } } } //Insert a zero width space char to make a new line or remove useless \n for (int i = 1; i < eb.Fields.Count; i++) { string efbStr = eb.Fields[i].Value.ToString(); if (i < eb.Fields.Count - 2) { eb.Fields[i].Value = efbStr + '\u200b'; } else { if (eb.Fields[i].Value == "empty") { eb.Fields.Remove(eb.Fields[i]); } else { eb.Fields[i].Value = efbStr.Remove(efbStr.Length - 1, 1); } } } await msg.EditAsync($"showing {beatmapPack.Count()} beatmaps", eb.Build()); }
private static void DrawPlayer() { bool shouldExit = false; Task.Run(delegate() { while (Console.ReadKey(true).Key != ConsoleKey.Escape) { } shouldExit = true; Program.relax.Stop(); Program.timewarp.Stop(); }); while (!shouldExit) { Console.Clear(); Console.WriteLine("Idling"); Console.WriteLine("\nPress ESC to return to the main menu."); while (!Program.osuManager.CanLoad && !shouldExit) { Thread.Sleep(5); } if (shouldExit) { break; } OsuBeatmap beatmap = Program.osuManager.Player.Beatmap; Console.Clear(); Console.WriteLine(string.Concat(new string[] { "Playing ", beatmap.Artist, " - ", beatmap.Title, " (", beatmap.Creator, ") [", beatmap.Version, "]" })); Console.WriteLine("\nPress ESC to return to the main menu."); Task task = Task.Factory.StartNew(delegate() { if (Program.configManager.EnableRelax && Program.osuManager.Player.CurrentRuleset == Ruleset.Standard) { Program.relax.Start(beatmap); } }); Task task2 = Task.Factory.StartNew(delegate() { if (Program.configManager.EnableTimewarp) { Program.timewarp.Start(); } }); Task.WaitAll(new Task[] { task, task2 }); } Program.DrawMainMenu(); }
public async Task GetBeatmap(string ID, string mode = null, string action = null) { SocketUserMessage msg = await Context.Channel.SendMessageAsync("Fetching data...", attachID : true); OsuGameModes gameMode = (string.IsNullOrEmpty(mode) ? OsuGameModes.None : OsuGameModesConverter.FromOfficialNumeration(byte.Parse(mode))); OsuBeatmap beatmap = await OsuNetwork.DownloadBeatmap(int.Parse(ID), gameMode, msg); gameMode = beatmap.GameMode; OsuUser creator = await OsuNetwork.DownloadUser(beatmap.Creator, OsuGameModes.STD, tolerateNull : true, maxAttempts : 3); Task <OsuScore[]> bestPlayDownloader = OsuNetwork.DownloadBeatmapBest(beatmap, gameMode, scoreCount: 3, logger: msg, tolerateNull: true, maxAttempts: 2); OsuBoundUserDB bound = await OsuDB.GetBoundUserBy_DiscordID(Context.Message.Author.ID); Task <OsuScore[]> boundBestScoreDownloader = OsuNetwork.DownloadBeatmapBest(beatmap, gameMode, user: bound.UserID, logger: msg, tolerateNull: true, maxAttempts: 3); EmbedBuilder eb = beatmap.ToEmbedBuilder(gameMode, creator); OsuScore[] bestPlays = await bestPlayDownloader; await msg.EditAsync("Fetching best plays...", null); if (bestPlays[0] != null) { EmbedFieldBuilder rankingsField = new EmbedFieldBuilder { Name = $"{CustomEmoji.Osu.Gamemode.GetGamemodeEmoji(beatmap.GameMode)}", Value = "report to LtLi0n" }; OsuUser[] bestPlayUsers = new OsuUser[bestPlays.Length]; int longestName = int.MinValue; for (int i = 0; i < bestPlays.Length; i++) { bestPlayUsers[i] = await OsuNetwork.DownloadUser(bestPlays[i].Username, beatmap.GameMode, logger : msg, maxAttempts : 2); if (bestPlayUsers[i].Username.Length > longestName) { longestName = bestPlayUsers[i].Username.Length; } } for (int i = 0; i < bestPlayUsers.Length; i++) { string toAdd = bestPlays[i].ToScoreString(bestPlayUsers[i].Country, gameMode, i + 1, nameFormat: '\u200b'); if (i == 0) { rankingsField.Value = toAdd; } else { rankingsField.Value += toAdd; } } rankingsField.IsInline = true; eb.AddField(rankingsField); if (bound != null) { try { OsuScore boundBestScore = (await boundBestScoreDownloader)[0]; if (boundBestScore != null) { eb.AddField(x => { x.Name = $"Your best"; x.Value = boundBestScore.ToScoreString(bound.Country, gameMode, includeReplay: boundBestScore.HasReplay, nameFormat: '\u200b'); x.IsInline = true; }); } } catch (Exception e) { } } } else { string[] lines_f1 = eb.Fields[0].Value.ToString().Split('\n'); lines_f1[0] += "\t\t\u200b"; string convertBack = ""; Tool.ForEach(lines_f1, x => convertBack += (x + '\n')); eb.Fields[0].Value = convertBack; eb.Fields[1].Value = '\u200b'; } string additional = string.Empty; if (action != null) { additional = action.ToLower() == "json" ? $"```json\n{JValue.Parse(JsonConvert.SerializeObject(beatmap)).ToString(Formatting.Indented)}```" : string.Empty; } await msg.EditAsync((additional), embed : eb.Build()); }