예제 #1
0
        public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore <byte[]> resources, GameHost host = null,
                              WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false)
            : base(storage, contextFactory, api, new BeatmapStore(contextFactory), host)
        {
            this.rulesets     = rulesets;
            this.audioManager = audioManager;
            this.resources    = resources;
            this.host         = host;

            DefaultBeatmap = defaultBeatmap;

            beatmaps = (BeatmapStore)ModelStore;
            beatmaps.BeatmapHidden   += b => beatmapHidden.Value = new WeakReference <BeatmapInfo>(b);
            beatmaps.BeatmapRestored += b => beatmapRestored.Value = new WeakReference <BeatmapInfo>(b);
            beatmaps.ItemRemoved     += removeWorkingCache;
            beatmaps.ItemUpdated     += removeWorkingCache;

            if (performOnlineLookups)
            {
                onlineLookupQueue = new BeatmapOnlineLookupQueue(api, storage);
            }

            largeTextureStore = new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store));
            trackStore        = audioManager.GetTrackStore(Files.Store);
        }
예제 #2
0
        private BeatmapStore createBeatmapStore(Func <OsuDbContext> context)
        {
            var store = new BeatmapStore(context);

            store.BeatmapSetAdded   += s => BeatmapSetAdded?.Invoke(s);
            store.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s);
            store.BeatmapHidden     += b => BeatmapHidden?.Invoke(b);
            store.BeatmapRestored   += b => BeatmapRestored?.Invoke(b);
            return(store);
        }
예제 #3
0
        public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, IIpcHost importHost = null)
            : base(storage, contextFactory, new BeatmapStore(contextFactory), importHost)
        {
            beatmaps = (BeatmapStore)ModelStore;
            beatmaps.BeatmapHidden   += b => BeatmapHidden?.Invoke(b);
            beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b);

            this.rulesets = rulesets;
            this.api      = api;
        }
예제 #4
0
        public BeatmapModelManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, GameHost host = null)
            : base(storage, contextFactory, new BeatmapStore(contextFactory), host)
        {
            this.rulesets = rulesets;

            beatmaps = (BeatmapStore)ModelStore;
            beatmaps.BeatmapHidden   += b => BeatmapHidden?.Invoke(b);
            beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b);
            beatmaps.ItemRemoved     += b => WorkingBeatmapCache?.Invalidate(b);
            beatmaps.ItemUpdated     += obj => WorkingBeatmapCache?.Invalidate(obj);
        }
예제 #5
0
        /// <summary>
        /// Returns a <see cref="BeatmapSetInfo"/> to a usable state if it has previously been deleted but not yet purged.
        /// Is a no-op for already usable beatmaps.
        /// </summary>
        /// <param name="beatmaps">The store to restore beatmaps from.</param>
        /// <param name="files">The store to restore beatmap files from.</param>
        /// <param name="beatmapSet">The beatmap to restore.</param>
        private void undelete(BeatmapStore beatmaps, FileStore files, BeatmapSetInfo beatmapSet)
        {
            if (!beatmaps.Undelete(beatmapSet))
            {
                return;
            }

            if (!beatmapSet.Protected)
            {
                files.Reference(beatmapSet.Files.Select(f => f.FileInfo).ToArray());
            }
        }
예제 #6
0
        public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, AudioManager audioManager, IIpcHost importHost = null,
                              WorkingBeatmap defaultBeatmap = null)
            : base(storage, contextFactory, new BeatmapStore(contextFactory), importHost)
        {
            this.rulesets     = rulesets;
            this.api          = api;
            this.audioManager = audioManager;

            DefaultBeatmap = defaultBeatmap;

            beatmaps = (BeatmapStore)ModelStore;
            beatmaps.BeatmapHidden   += b => BeatmapHidden?.Invoke(b);
            beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b);
        }
예제 #7
0
        public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null,
                              WorkingBeatmap defaultBeatmap = null)
            : base(storage, contextFactory, new BeatmapStore(contextFactory), host)
        {
            this.rulesets     = rulesets;
            this.api          = api;
            this.audioManager = audioManager;
            this.host         = host;

            DefaultBeatmap = defaultBeatmap;

            beatmaps = (BeatmapStore)ModelStore;
            beatmaps.BeatmapHidden   += b => BeatmapHidden?.Invoke(b);
            beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b);
        }
예제 #8
0
        public BeatmapManager(Storage storage, FileStore files, SQLiteConnection connection, RulesetStore rulesets, IIpcHost importHost = null)
        {
            beatmaps = new BeatmapStore(connection);
            beatmaps.BeatmapSetAdded   += s => BeatmapSetAdded?.Invoke(s);
            beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s);

            this.storage  = storage;
            this.files    = files;
            this.rulesets = rulesets;

            if (importHost != null)
            {
                ipc = new BeatmapIPCChannel(importHost, this);
            }
        }
예제 #9
0
        public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null,
                              WorkingBeatmap defaultBeatmap = null)
            : base(storage, contextFactory, api, new BeatmapStore(contextFactory), host)
        {
            this.rulesets     = rulesets;
            this.audioManager = audioManager;
            this.host         = host;

            DefaultBeatmap = defaultBeatmap;

            beatmaps = (BeatmapStore)ModelStore;
            beatmaps.BeatmapHidden   += b => beatmapHidden.Value = new WeakReference <BeatmapInfo>(b);
            beatmaps.BeatmapRestored += b => beatmapRestored.Value = new WeakReference <BeatmapInfo>(b);

            onlineLookupQueue = new BeatmapOnlineLookupQueue(api, storage);
        }
예제 #10
0
        public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null,
                              WorkingBeatmap defaultBeatmap = null)
            : base(storage, contextFactory, api, new BeatmapStore(contextFactory), host)
        {
            this.rulesets     = rulesets;
            this.audioManager = audioManager;
            this.host         = host;

            DefaultBeatmap = defaultBeatmap;

            beatmaps = (BeatmapStore)ModelStore;
            beatmaps.BeatmapHidden   += b => BeatmapHidden?.Invoke(b);
            beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b);

            onlineLookupQueue = new BeatmapOnlineLookupQueue(api, storage);
            exportStorage     = storage.GetStorageForDirectory("exports");
        }
예제 #11
0
        public BeatmapManager(Storage storage, Func <OsuDbContext> context, RulesetStore rulesets, APIAccess api, IIpcHost importHost = null)
        {
            createContext = context;

            refreshImportContext();

            beatmaps = createBeatmapStore(context);
            files    = new FileStore(context, storage);

            this.storage  = files.Storage;
            this.rulesets = rulesets;
            this.api      = api;

            if (importHost != null)
            {
                ipc = new BeatmapIPCChannel(importHost, this);
            }

            beatmaps.Cleanup();
        }
예제 #12
0
        public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, IIpcHost importHost = null)
        {
            this.contextFactory = contextFactory;

            beatmaps = new BeatmapStore(contextFactory);

            beatmaps.BeatmapSetAdded   += s => BeatmapSetAdded?.Invoke(s);
            beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s);
            beatmaps.BeatmapHidden     += b => BeatmapHidden?.Invoke(b);
            beatmaps.BeatmapRestored   += b => BeatmapRestored?.Invoke(b);

            files = new FileStore(contextFactory, storage);

            this.rulesets = rulesets;
            this.api      = api;

            if (importHost != null)
            {
                ipc = new BeatmapIPCChannel(importHost, this);
            }

            beatmaps.Cleanup();
        }
예제 #13
0
        public BeatmapManager(Storage storage, Func <OsuDbContext> context, RulesetStore rulesets, APIAccess api, IIpcHost importHost = null)
        {
            createContext = context;
            importContext = new Lazy <OsuDbContext>(() =>
            {
                var c = createContext();
                c.Database.AutoTransactionsEnabled = false;
                return(c);
            });

            beatmaps = createBeatmapStore(context);
            files    = new FileStore(context, storage);

            this.storage  = files.Storage;
            this.rulesets = rulesets;
            this.api      = api;

            if (importHost != null)
            {
                ipc = new BeatmapIPCChannel(importHost, this);
            }

            beatmaps.Cleanup();
        }
예제 #14
0
        /// <summary>
        /// Import a beamap into our local <see cref="FileStore"/> storage.
        /// If the beatmap is already imported, the existing instance will be returned.
        /// </summary>
        /// <param name="files">The store to import beatmap files to.</param>
        /// <param name="beatmaps">The store to import beatmaps to.</param>
        /// <param name="reader">The beatmap archive to be read.</param>
        /// <returns>The imported beatmap, or an existing instance if it is already present.</returns>
        private BeatmapSetInfo importToStorage(FileStore files, BeatmapStore beatmaps, ArchiveReader reader)
        {
            // let's make sure there are actually .osu files to import.
            string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu"));

            if (string.IsNullOrEmpty(mapName))
            {
                throw new InvalidOperationException("No beatmap files found in the map folder.");
            }

            // for now, concatenate all .osu files in the set to create a unique hash.
            MemoryStream hashable = new MemoryStream();

            foreach (string file in reader.Filenames.Where(f => f.EndsWith(".osu")))
            {
                using (Stream s = reader.GetStream(file))
                    s.CopyTo(hashable);
            }

            var hash = hashable.ComputeSHA2Hash();

            // check if this beatmap has already been imported and exit early if so.
            var beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.Hash == hash);

            if (beatmapSet != null)
            {
                undelete(beatmaps, files, beatmapSet);

                // ensure all files are present and accessible
                foreach (var f in beatmapSet.Files)
                {
                    if (!storage.Exists(f.FileInfo.StoragePath))
                    {
                        using (Stream s = reader.GetStream(f.Filename))
                            files.Add(s, false);
                    }
                }

                // todo: delete any files which shouldn't exist any more.

                return(beatmapSet);
            }

            List <BeatmapSetFileInfo> fileInfos = new List <BeatmapSetFileInfo>();

            // import files to manager
            foreach (string file in reader.Filenames)
            {
                using (Stream s = reader.GetStream(file))
                    fileInfos.Add(new BeatmapSetFileInfo
                    {
                        Filename = file,
                        FileInfo = files.Add(s)
                    });
            }

            BeatmapMetadata metadata;

            using (var stream = new StreamReader(reader.GetStream(mapName)))
                metadata = Decoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata;


            // check if a set already exists with the same online id.
            if (metadata.OnlineBeatmapSetID != null)
            {
                beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID);
            }

            if (beatmapSet == null)
            {
                beatmapSet = new BeatmapSetInfo
                {
                    OnlineBeatmapSetID = metadata.OnlineBeatmapSetID,
                    Beatmaps           = new List <BeatmapInfo>(),
                    Hash     = hash,
                    Files    = fileInfos,
                    Metadata = metadata
                }
            }
            ;


            var mapNames = reader.Filenames.Where(f => f.EndsWith(".osu"));

            foreach (var name in mapNames)
            {
                using (var raw = reader.GetStream(name))
                    using (var ms = new MemoryStream()) //we need a memory stream so we can seek and shit
                        using (var sr = new StreamReader(ms))
                        {
                            raw.CopyTo(ms);
                            ms.Position = 0;

                            var     decoder = Decoder.GetDecoder(sr);
                            Beatmap beatmap = decoder.DecodeBeatmap(sr);

                            beatmap.BeatmapInfo.Path    = name;
                            beatmap.BeatmapInfo.Hash    = ms.ComputeSHA2Hash();
                            beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();

                            var existing = beatmaps.Beatmaps.FirstOrDefault(b => b.Hash == beatmap.BeatmapInfo.Hash || beatmap.BeatmapInfo.OnlineBeatmapID != null && b.OnlineBeatmapID == beatmap.BeatmapInfo.OnlineBeatmapID);

                            if (existing == null)
                            {
                                // Exclude beatmap-metadata if it's equal to beatmapset-metadata
                                if (metadata.Equals(beatmap.Metadata))
                                {
                                    beatmap.BeatmapInfo.Metadata = null;
                                }

                                RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);

                                // TODO: this should be done in a better place once we actually need to dynamically update it.
                                beatmap.BeatmapInfo.Ruleset        = ruleset;
                                beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0;

                                beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo);
                            }
                        }
            }

            return(beatmapSet);
        }