// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Users; namespace osu.Game.Online.Multiplayer { public class Room { [JsonProperty("id")] public Bindable RoomID { get; } = new Bindable(); [JsonProperty("name")] public readonly Bindable Name = new Bindable("My awesome room!"); [JsonProperty("host")] public readonly Bindable Host = new Bindable(); public bool ShouldSerializeHost() => false; [JsonProperty("playlist")] public readonly BindableCollection Playlist = new BindableCollection(); [JsonProperty("duration")] public readonly Bindable Duration = new Bindable(100); [JsonIgnore] public readonly Bindable MaxAttempts = new Bindable(); // Todo: Find a better way to do this (https://github.com/ppy/osu-framework/issues/1930) [JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)] private int? maxAttempts { get => MaxAttempts; set => MaxAttempts.Value = value; } public Bindable Status = new Bindable(new RoomStatusOpen()); public Bindable Availability = new Bindable(); public Bindable Type = new Bindable(new GameTypeTimeshift()); public Bindable MaxParticipants = new Bindable(); public Bindable> Participants = new Bindable>(Enumerable.Empty()); public void CopyFrom(Room other) { RoomID.Value = other.RoomID; Name.Value = other.Name; Host.Value = other.Host; Status.Value = other.Status; Availability.Value = other.Availability; Type.Value = other.Type; MaxParticipants.Value = other.MaxParticipants; Participants.Value = other.Participants.Value.ToArray(); Playlist.Clear(); Playlist.AddRange(other.Playlist); } } public class PlaylistItem { [JsonProperty("id")] public int ID { get; set; } [JsonProperty("beatmap")] private APIBeatmap apiBeatmap { get; set; } public bool ShouldSerializeapiBeatmap() => false; private BeatmapInfo beatmap; [JsonIgnore] public BeatmapInfo Beatmap { get => beatmap; set { beatmap = value; BeatmapID = value?.OnlineBeatmapID ?? 0; } } [JsonProperty("beatmap_id")] public int BeatmapID { get; set; } [JsonProperty("ruleset_id")] public int RulesetID { get; set; } [JsonIgnore] public readonly BindableCollection AllowedMods = new BindableCollection(); [JsonIgnore] public readonly BindableCollection RequiredMods = new BindableCollection(); private APIMod[] _allowedMods; [JsonProperty("allowed_mods")] private APIMod[] allowedMods { get => AllowedMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); set => _allowedMods = value; } private APIMod[] _requiredMods; [JsonProperty("required_mods")] private APIMod[] requiredMods { get => RequiredMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); set => _requiredMods = value; } [JsonIgnore] public RulesetInfo Ruleset { get; set; } public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) { // If we don't have an api beatmap, the request occurred as a result of room creation, so we can query the local beatmap instead // Todo: Is this a bug? Beatmap = apiBeatmap == null ? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == BeatmapID) : apiBeatmap.ToBeatmap(rulesets); Ruleset = rulesets.GetRuleset(RulesetID); if (_allowedMods != null) { AllowedMods.Clear(); AllowedMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _allowedMods.Any(m => m.Acronym == mod.Acronym))); _allowedMods = null; } if (_requiredMods != null) { RequiredMods.Clear(); RequiredMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _requiredMods.Any(m => m.Acronym == mod.Acronym))); _requiredMods = null; } } // Todo: Move this elsewhere for reusability private class APIMod : IMod { public string Acronym { get; set; } } } }