Example #1
0
        /// <summary>
        ///     Creates a new mapset with an audio file.
        /// </summary>
        /// <param name="audioFile"></param>
        public static void HandleNewMapsetCreation(string audioFile)
        {
            try
            {
                var game = GameBase.Game as QuaverGame;

                // Add a fade effect and make butotns not clickable
                // so the user can't perform any actions during this time.
                Transitioner.FadeIn();
                Button.IsGloballyClickable = false;

                var tagFile = TagLib.File.Create(audioFile);

                // Create a fresh .qua with the available metadata from the file
                var qua = new Qua()
                {
                    AudioFile      = Path.GetFileName(audioFile),
                    Artist         = tagFile.Tag.FirstPerformer ?? "",
                    Title          = tagFile.Tag.Title ?? "",
                    Source         = tagFile.Tag.Album ?? "",
                    Tags           = string.Join(" ", tagFile.Tag.Genres) ?? "",
                    Creator        = ConfigManager.Username.Value,
                    DifficultyName = "",
                    // Makes the file different to prevent exception thrown in the DB for same md5 checksum
                    Description    = $"Created at {TimeHelper.GetUnixTimestampMilliseconds()}",
                    BackgroundFile = "",
                    Mode           = GameMode.Keys4
                };

                // Create a new directory to house the map.
                var dir = $"{ConfigManager.SongDirectory.Value}/{TimeHelper.GetUnixTimestampMilliseconds()}";
                Directory.CreateDirectory(dir);

                // Copy over the audio file into the directory
                File.Copy(audioFile, $"{dir}/{Path.GetFileName(audioFile)}");

                // Save the new .qua file into the directory
                var path = $"{dir}/{StringHelper.FileNameSafeString($"{qua.Artist} - {qua.Title} [{qua.DifficultyName}] - {TimeHelper.GetUnixTimestampMilliseconds()}")}.qua";
                qua.Save(path);

                // Place the new map inside of the database and make sure all the loaded maps are correct
                var map = Map.FromQua(qua, path);
                map.Id = MapDatabaseCache.InsertMap(map, path);
                MapDatabaseCache.OrderAndSetMapsets();

                MapManager.Selected.Value     = map;
                MapManager.Selected.Value.Qua = qua;

                var selectedMapset = MapManager.Mapsets.Find(x => x.Maps.Any(y => y.Id == MapManager.Selected.Value.Id));

                // Find the new object from the loaded maps that contains the same id.
                MapManager.Selected.Value              = selectedMapset.Maps.Find(x => x.Id == MapManager.Selected.Value.Id);
                MapManager.Selected.Value.Qua          = qua;
                MapManager.Selected.Value.NewlyCreated = true;

                game?.CurrentScreen.Exit(() => new EditorScreen(qua));
            }
            catch (Exception e)
            {
                Logger.Error(e, LogType.Runtime);

                var game = GameBase.Game as QuaverGame;

                game?.CurrentScreen.Exit(() =>
                {
                    NotificationManager.Show(NotificationLevel.Error, "Could not create new mapset with that audio file.");
                    return(new SelectScreen());
                });
            }
        }
Example #2
0
        private static int Merge(string ancestorPath, string ourPath, string theirPath, int blockSize = 1000)
        {
            // hitobjects, timing points, scroll velocities, preview points, editor layers
            // key counts, diff names
            // audio file, background file, banner file
            // map id, mapset id
            // song title, song artist, song source
            // tags, creator, description, genre
            // initial sv, sv mode, scratch key
            // custom audio samples, sound effects
            Qua ancestor = Qua.Parse(ancestorPath, false);
            Qua ours     = Qua.Parse(ourPath, false);
            Qua theirs   = Qua.Parse(theirPath, false);

            ancestor.Sort();
            ours.Sort();
            theirs.Sort();

            int mergeConflicts = 0;

            Console.WriteLine("Merging Layers...");
            List <EditorLayerInfo> mergeLayers = GenerateIndexBasedMergeObjects <EditorLayerInfo>(ancestor.EditorLayers, ours.EditorLayers, theirs.EditorLayers,
                                                                                                  ancestor.HitObjects, ours.HitObjects, theirs.HitObjects,
                                                                                                  EditorLayerInfo.ByValueComparer,
                                                                                                  ApplyLayerIndexChanges);

            // untested
            Console.WriteLine("Merging Custom Audio Samples...");
            List <CustomAudioSampleInfo> mergeCustomAudioSamples = GenerateIndexBasedMergeObjects <CustomAudioSampleInfo>(ancestor.CustomAudioSamples, ours.CustomAudioSamples, theirs.CustomAudioSamples,
                                                                                                                          ancestor.HitObjects, ours.HitObjects, theirs.HitObjects,
                                                                                                                          CustomAudioSampleInfo.ByValueComparer,
                                                                                                                          ApplyKeySoundSampleIndexChanges);

            // untested
            Console.WriteLine("Merging Sound Effects...");
            List <SoundEffectInfo> mergeSoundEffects = MergeLists(ancestor.SoundEffects, ours.SoundEffects, theirs.SoundEffects, new List <SoundEffectInfo>(), SoundEffectInfo.ByValueComparer, ref mergeConflicts);

            float?minTime = new float?[9]
            {
                ancestor.HitObjects.Count > 0 ? (float)ancestor.HitObjects[0].StartTime : (float?)null,
                ancestor.TimingPoints.Count > 0 ? ancestor.TimingPoints[0].StartTime : (float?)null,
                ancestor.SliderVelocities.Count > 0 ? ancestor.SliderVelocities[0].StartTime : (float?)null,
                ours.HitObjects.Count > 0 ? (float)ours.HitObjects[0].StartTime : (float?)null,
                ours.TimingPoints.Count > 0 ? ours.TimingPoints[0].StartTime : (float?)null,
                ours.SliderVelocities.Count > 0 ? ours.SliderVelocities[0].StartTime : (float?)null,
                theirs.HitObjects.Count > 0 ? (float)theirs.HitObjects[0].StartTime : (float?)null,
                theirs.TimingPoints.Count > 0 ? theirs.TimingPoints[0].StartTime : (float?)null,
                theirs.SliderVelocities.Count > 0 ? theirs.SliderVelocities[0].StartTime : (float?)null
            }.Min();

            Console.WriteLine("minTime: " + minTime);

            float?maxTime = new float?[9]
            {
                ancestor.HitObjects.Count > 0 ? (float)ancestor.HitObjects.Last().StartTime : (float?)null,
                ancestor.TimingPoints.Count > 0 ? ancestor.TimingPoints.Last().StartTime : (float?)null,
                ancestor.SliderVelocities.Count > 0 ? ancestor.SliderVelocities.Last().StartTime : (float?)null,
                ours.HitObjects.Count > 0 ? (float)ours.HitObjects.Last().StartTime : (float?)null,
                ours.TimingPoints.Count > 0 ? ours.TimingPoints.Last().StartTime : (float?)null,
                ours.SliderVelocities.Count > 0 ? ours.SliderVelocities.Last().StartTime : (float?)null,
                theirs.HitObjects.Count > 0 ? (float)theirs.HitObjects.Last().StartTime : (float?)null,
                theirs.TimingPoints.Count > 0 ? theirs.TimingPoints.Last().StartTime : (float?)null,
                theirs.SliderVelocities.Count > 0 ? theirs.SliderVelocities.Last().StartTime : (float?)null
            }.Max();

            Console.WriteLine("maxTime: " + maxTime);

            List <Block> mergeBlocks;

            if (minTime != null && maxTime != null)
            {
                mergeBlocks = GenerateMergeBlocks(ancestor, ours, theirs, (float)minTime, (float)maxTime, blockSize, ref mergeConflicts);
            }
            else
            {
                mergeBlocks = new List <Block>();
            }

            Console.WriteLine("Generating Merged Map");

            Qua mergeQua = new Qua
            {
                AudioFile       = MergeMetadata <string>(ancestor.AudioFile, ours.AudioFile, theirs.AudioFile, "MERGE CONFLICT", ref mergeConflicts),
                SongPreviewTime = MergeMetadata <int>(ancestor.SongPreviewTime, ours.SongPreviewTime, theirs.SongPreviewTime, -1, ref mergeConflicts),
                BackgroundFile  = MergeMetadata <string>(ancestor.BackgroundFile, ours.BackgroundFile, theirs.BackgroundFile, "MERGE CONFLICT", ref mergeConflicts),
                BannerFile      = MergeMetadata <string>(ancestor.BannerFile, ours.BannerFile, theirs.BannerFile, "MERGE CONFLICT", ref mergeConflicts),
                MapId           = MergeMetadata <int>(ancestor.MapId, ours.MapId, theirs.MapId, -1, ref mergeConflicts),
                MapSetId        = MergeMetadata <int>(ancestor.MapSetId, ours.MapSetId, theirs.MapSetId, -1, ref mergeConflicts),
                // why would anyone merge 4k and 7k together
                Mode           = MergeMetadata <GameMode>(ancestor.Mode, ours.Mode, theirs.Mode, (GameMode)(-1), ref mergeConflicts),
                Title          = MergeMetadata <string>(ancestor.Title, ours.Title, theirs.Title, "MERGE CONFLICT", ref mergeConflicts),
                Artist         = MergeMetadata <string>(ancestor.Artist, ours.Artist, theirs.Artist, "MERGE CONFLICT", ref mergeConflicts),
                Source         = MergeMetadata <string>(ancestor.Source, ours.Source, theirs.Source, "MERGE CONFLICT", ref mergeConflicts),
                Tags           = MergeMetadata <string>(ancestor.Tags, ours.Tags, theirs.Tags, "MERGE CONFLICT", ref mergeConflicts),
                Creator        = MergeMetadata <string>(ancestor.Creator, ours.Creator, theirs.Creator, "MERGE CONFLICT", ref mergeConflicts),
                DifficultyName = MergeMetadata <string>(ancestor.DifficultyName, ours.DifficultyName, theirs.DifficultyName, "MERGE CONFLICT", ref mergeConflicts),
                Description    = MergeMetadata <string>(ancestor.Description, ours.Description, theirs.Description, "MERGE CONFLICT", ref mergeConflicts),
                Genre          = MergeMetadata <string>(ancestor.Genre, ours.Genre, theirs.Genre, "MERGE CONFLICT", ref mergeConflicts),
                BPMDoesNotAffectScrollVelocity = MergeMetadata <bool>(ancestor.BPMDoesNotAffectScrollVelocity, ours.BPMDoesNotAffectScrollVelocity, theirs.BPMDoesNotAffectScrollVelocity, true, ref mergeConflicts),
                InitialScrollVelocity          = MergeMetadata <float>(ancestor.InitialScrollVelocity, ours.InitialScrollVelocity, theirs.InitialScrollVelocity, -1, ref mergeConflicts),
                HasScratchKey      = MergeMetadata <bool>(ancestor.HasScratchKey, ours.HasScratchKey, theirs.HasScratchKey, false, ref mergeConflicts),
                CustomAudioSamples = mergeCustomAudioSamples
            };

            mergeQua.EditorLayers.AddRange(mergeLayers);
            mergeQua.SoundEffects.AddRange(mergeSoundEffects); // untested

            var objects = GenerateListsFromBlocks(mergeBlocks);

            mergeQua.HitObjects.AddRange(objects.HitObjects);
            mergeQua.TimingPoints.AddRange(objects.TimingPoints);
            mergeQua.SliderVelocities.AddRange(objects.ScrollVelocities);

            Console.WriteLine("Writing .qua File at " + ourPath);

            // git expected behavior: overwrite our file
            mergeQua.Save(ourPath);

            return(mergeConflicts);
        }