public SQLiteData(SQLiteDataReader data) { foreach (FieldInfo prop in GetType().GetFields()) { try { switch (prop.Name.ToLower()) { case "datet": prop.SetValue(this, data[prop.Name.ToLower()].ToString()); break; default: prop.SetValue(this, data[prop.Name.ToLower()]); break; } } catch { try { PulsarcLogger.Warning($"Data field in SQLite request could not be set as a {prop.FieldType.Name} : {data[prop.Name.ToLower()]}", LogType.Runtime); } catch { PulsarcLogger.Warning($"Unexpected data field in SQLite request : {prop.Name}", LogType.Runtime); } } } }
/// <summary> /// Start playing audio /// </summary> public static void StartLazyPlayer() { Stop(); if (songPath == "") { return; } // Initialize the song try { song = new AudioTrack(songPath) { Rate = audioRate, Volume = Config.GetInt("Audio", "MusicVolume"), }; } catch (AudioEngineException) { PulsarcLogger.Error(ManagedBass.Bass.LastError.ToString(), LogType.Runtime); } song.ApplyRate(Config.GetBool("Audio", "RatePitch")); song.Play(); active = true; }
/// <summary> /// Save this setting into the config.ini file. /// </summary> /// <param name="category">Category to save under</param> /// <param name="key">The key to modify.</param> public virtual void Save(string category, string key) { switch (Type) { case "float": Config.SetFloat(category, key, (float)GetSaveValue()); break; case "int": Config.SetInt(category, key, (int)GetSaveValue()); break; case "double": Config.SetDouble(category, key, (double)GetSaveValue()); break; case "bool": Config.SetBool(category, key, (bool)GetSaveValue()); break; case "string": Config.SetString(category, key, (string)GetSaveValue()); break; default: PulsarcLogger.Error($"Cannot save type {Type.ToString()} in category {category} for setting {key}", LogType.Runtime); break; } }
/// <summary> /// Initializes the current GameplayView with the provided beatmap. /// </summary> /// <param name="beatmap">The beatmap to play through</param> public void Init(Beatmap beatmap) { try { if (!beatmap.FullyLoaded) { beatmap = BeatmapHelper.Load(beatmap.Path, beatmap.FileName); } // Reset in case it wasn't properly handled outside Reset(); // Load values gained from config/user settings LoadConfig(beatmap); // Initialize default variables, parse beatmap InitializeVariables(beatmap); // Initialize Gameplay variables InitializeGameplay(beatmap); // Create columns and their hitobjects CreateColumns(); // Sort the hitobjects according to their first appearance for optimizing update/draw SortHitObjects(); if (AutoPlay) { LoadAutoPlay(); } // Once everything is loaded, initialize the view GetGameplayView().Init(); // Start audio and gameplay StartGameplay(); // Collect any excess memory to prevent GC from starting soon, avoiding freezes. // TODO: disable GC while in gameplay GC.Collect(); Init(); } catch { // Force quit EndGameplay(); // Give warning PulsarcLogger.Warning($"There was an error attempting to load {beatmap.Title}, " + $"going back to Song Select!"); // Remove Result Screen ScreenManager.RemoveScreen(); } }
/// <summary> /// Initializes a setting that can change different options in Pulsarc. /// </summary> /// <param name="title">Name of the Setting</param> /// <param name="more"></param> /// <param name="position">Setting's position.</param> /// <param name="texture">The texture for the Setting.</param> /// <param name="anchor">The anchor position for this Setting.</param> /// <param name="baseValue">The value this setting starts with.</param> /// <param name="type">The type of variable this setting changes.</param> public Setting(string title, string more, Vector2 position, Texture2D texture, Anchor anchor, dynamic baseValue, string type) : base(texture, position, anchor: anchor) { Value = baseValue; Type = type; PulsarcLogger.Important($"{type} set for {title}", LogType.Runtime); Text = title; Title = new TextDisplayElement(title, new Vector2(position.X - 50, position.Y), anchor: Anchor.CenterRight); }
/// <summary> /// Converts an Intralism beatmap folder to a Pulsarc-compatible beatmap, and then saves the converted Beatmap to storage. /// </summary> /// <param name="folder_path">The path to the map-to-be-converted folder</param> public void Save(string folder_path) { Beatmap map = Convert(folder_path).First(); // If the map is null, or audio is null, stop saving. if (map == null || map.Audio == null) { return; } string audioPath = $"{folder_path}/{map.Audio}"; // If the path doesn't exist, stop saving. if (!File.Exists(audioPath)) { return; } int id = 0; // The folder name will look like "0 - Unknown - MapTitle - (Mapper)" string folderName = string.Join("_", ($"{id} - {map.Artist} - {map.Title} ({map.Mapper})").Split(Path.GetInvalidFileNameChars())); string dirName = $"Songs/{folderName}"; if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } // Copy Audio File File.Copy(audioPath, $"{dirName}/{map.Audio}", true); // Copy Background Image string backgroundPath = $"{folder_path}/{map.Background}"; // Find if the background exists and copy it. if (File.Exists(backgroundPath)) { try { File.Copy(backgroundPath, $"{dirName}/{map.Background}", true); } catch { PulsarcLogger.Debug("Converting the background failed! Converting wtihout background.", LogType.Runtime); } } else { map.Background = ""; } // The file name will look like "Unknown - MapTitle [Converted] (Mapper).psc" string difficultyFileName = string.Join("_", ($"{map.Artist} - {map.Title} [{map.Version}] ({map.Mapper})").Split(Path.GetInvalidFileNameChars())); BeatmapHelper.Save(map, $"{dirName}/{difficultyFileName}.psc"); }
/// <summary> /// Write a property to file /// </summary> /// <param name="file"></param> /// <param name="beatmap"></param> /// <param name="property"></param> static private void WriteProperty(StreamWriter file, Beatmap beatmap, string property) { try { // Use reflection to write any property. The property needs to implement ToString() file.WriteLine(property + ": " + beatmap.GetType().GetProperty(property).GetValue(beatmap, null)); } catch { PulsarcLogger.Error($"Trying to write invalid property {property}", LogType.Runtime); } }
/// <summary> /// Load a skin from the folder name provided. /// </summary> /// <param name="name">The folder name of the skin to be loaded.</param> public static void LoadSkin(string name) { Assets = new Dictionary <string, Texture2D>(); Configs = new Dictionary <String, IniData>(); Judges = new Dictionary <int, Texture2D>(); Sounds = new Dictionary <string, AudioSample>(); Loaded = false; string skinFolder = $"Skins/{name}/"; if (Directory.Exists(skinFolder)) { // Load configs LoadConfigs(skinFolder); // Load gameplay assets LoadSkinTexture($"{skinFolder}Gameplay/", "arcs"); LoadSkinTexture($"{skinFolder}Gameplay/", "crosshair"); LoadSkinTexture($"{skinFolder}Gameplay/", "map_timer"); // Load cursor asset LoadSkinTexture($"{skinFolder}UI/", "cursor"); // Load Main Menu assets LoadMainMenu(skinFolder); // Load Result Screen assets (not including Grades) LoadResultScreen(skinFolder); // Load Song Select assets LoadSongSelect(skinFolder); // Load settings assets LoadSettings(skinFolder); // Load Grade assets LoadGrades(skinFolder); // Load judge assets LoadJudges(skinFolder); // Load sounds LoadSounds(skinFolder); Loaded = true; } else { PulsarcLogger.Error($"Could not find the skin {name}", LogType.Network); } }
public static Texture2D LoadFileTexture(string path) { Texture2D texture; try { texture = Texture2D.FromStream(Pulsarc.Graphics.GraphicsDevice, File.Open(path, FileMode.Open)); } catch { PulsarcLogger.Error($"Failed to load {path}", LogType.Runtime); texture = Skin.DefaultTexture; } return(texture); }
public override void Draw() { if (caught) { return; } try { Pulsarc.SpriteBatch.DrawString(font, Text, processedPosition, Color, 0, origin, fontScale, SpriteEffects.None, 0); } catch { PulsarcLogger.Error($"Could not write {Text}, Aborting Draw() calls for this TextDisplayElement until Update() has been called.", LogType.Runtime); caught = true; // Don't need to spam the console with Errors } }
/// <summary> /// Initialize most static objects and dependencies /// </summary> protected override void Initialize() { base.Initialize(); // Copy, if needed, the required assemblies (BASS) for 32 or 64bit CPUs NativeAssemblies.Copy(); // Initialize the logging tool for troubleshooting PulsarcLogger.Initialize(); // Initialize Discord Rich Presence PulsarcDiscord.Initialize(); // Set the default culture (Font formatting Locals) for this thread Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; // Start the thread listening for user input InputManager.StartThread(); // Start our time and frame-time tracker PulsarcTime.Start(); // Initialize FPS fpsDisplay = new FPS(Vector2.Zero); // Initialize the game camera gameCamera = new Camera(Graphics.GraphicsDevice.Viewport, (int)GetDimensions().X, (int)GetDimensions().Y, 1) { Pos = new Vector2(GetDimensions().X / 2, GetDimensions().Y / 2) }; // Start the song selection in the background to have music when entering the game SongScreen = new SongSelection(); SongScreen.Init(); // Create and display the default game screen // (Currently Main menu. In the future can implement an intro) Menu firstScreen = new Menu(); ScreenManager.AddScreen(firstScreen); cursor = new Cursor(); IsReadyToUpdate = true; }
/// <summary> /// Attempts to return the texture found using the folder path and file asset name provided. /// </summary> /// <param name="path">The folder loaction of the texture.</param> /// <param name="asset">The name of the file to load.</param> /// <returns>A texture using the image file found, or an uninitialized "Default Texture" if the asset can't be loaded.</returns> private static Texture2D LoadTexture(string path, string asset) { // Try opening as a .png try { return(Texture2D.FromStream(Pulsarc.Graphics.GraphicsDevice, File.Open($"{path}/{asset}.png", FileMode.Open))); } catch { // Try opening as a .jpg try { return(Texture2D.FromStream(Pulsarc.Graphics.GraphicsDevice, File.Open($"{path}/{asset}.jpg", FileMode.Open))); } // Don't load, throw a console error, and return default texture. catch { PulsarcLogger.Warning($"Failed to load {asset} in {path}, make sure it is a .png or .jpg file!", LogType.Runtime); return(DefaultTexture); } } }
/// <summary> /// Change the the audio rate to the one defined /// in the config. /// </summary> public static void UpdateRate() { if (active) { // Save the position and audio path. double time = GetTime(); string audio = songPath; Stop(); // Find the audio rate. songPath = audio; audioRate = Config.GetFloat("Gameplay", "SongRate"); StartLazyPlayer(); // Play the rate-changed song at the time saved earlier. if (time != 0) { DeltaTime((long)time); } PulsarcLogger.Important($"Now Playing: {songPath} at {audioRate} rate", LogType.Runtime); } }
/// <summary> /// Load a single Beatmap. /// </summary> /// <param name="path">The path to the beatmap folder.</param> /// <param name="fileName">The fileName of the .psc file.</param> static public Beatmap Load(string path, string fileName) { Beatmap parsed = new Beatmap(); parsed.Path = path; parsed.FileName = fileName; var state = ""; var lines = File.ReadLines($"{path}/{fileName}"); foreach (var line in lines) { if (line.Length > 0) { // Information like Metadata are in the form 'Type: Data' Queue <string> lineParts = new Queue <string>(line.Split(':')); // If we recognize this form, it's an attribute. // Otherwise, it is a more complex data form, like an event if (lineParts.Count > 1) { var type = lineParts.Dequeue(); var rightPart = string.Concat(lineParts.ToArray()).Trim(); // Use reflection to set the Beatmap's attributes switch (type) { case "FormatVersion": case "Title": case "Artist": case "Mapper": case "Version": case "MapOffset": try { parsed.GetType().GetProperty(type).SetValue(parsed, rightPart); } catch { PulsarcLogger.Error($"Unknown beatmap field : {type}", LogType.Runtime); } break; case "Audio": try { parsed.GetType().GetProperty(type).SetValue(parsed, rightPart); } catch { PulsarcLogger.Error($"Unknown beatmap field : {type}", LogType.Runtime); } break; case "Background": { try { parsed.GetType().GetProperty(type).SetValue(parsed, rightPart); } catch { PulsarcLogger.Error($"Unknown beatmap field : {type}", LogType.Runtime); } break; } case "PreviewTime": case "KeyCount": try { parsed.GetType().GetProperty(type).SetValue(parsed, int.Parse(rightPart)); } catch { PulsarcLogger.Error($"Unknown beatmap field : {type}", LogType.Runtime); } break; case "Difficulty": try { parsed.GetType().GetProperty(type).SetValue(parsed, Double.Parse(rightPart, CultureInfo.InvariantCulture)); } catch { PulsarcLogger.Error($"Unknown beatmap field : {type}", LogType.Runtime); } break; case "Events": case "TimingPoints": case "SpeedVariations": case "Arcs": state = type; break; default: // Should probably ingore this really, like why would we need to know that? //PulsarcLogger.Error($"Unknown beatmap field : {type}", LogType.Runtime); break; } } else { // Each event is comma separated and can have any amount of values. var eventParts = line.Split(','); // Handling depends on the data type (or the current reading state) switch (state) { case "Events": try { int type = int.Parse(eventParts[(int)EventIndex.Type]); Event evnt = MakeEvent(line, (EventType)type); if (evnt != null) { parsed.Events.Add(evnt); } } catch { PulsarcLogger.Error($"Invalid Event : {line}", LogType.Runtime); } break; case "TimingPoints": try { parsed.TimingPoints.Add(new TimingPoint(Convert.ToInt32(eventParts[0]), Convert.ToInt32(eventParts[1]))); } catch { PulsarcLogger.Error($"Invalid TimingPoint : {line}", LogType.Runtime); } break; case "Arcs": try { parsed.Arcs.Add(new Arc(Convert.ToInt32(eventParts[0]), Convert.ToInt32(eventParts[1], 2))); } catch { PulsarcLogger.Error($"Invalid Arc : {line}", LogType.Runtime); } break; default: PulsarcLogger.Error($"Invalid state : {line}", LogType.Runtime); break; } } } } // If no difficulty has been provided in the game file, process it now. if (parsed.Difficulty == 0) { parsed.Difficulty = DifficultyCalculation.GetDifficulty(parsed); } parsed.FullyLoaded = true; return(parsed); }
private async void ConvertMaps() { // Temporary measure for converting intralism or osu!mania beatmaps // TODO Make a Converter UI if (!converting && !GameplayEngine.Active && Keyboard.GetState().IsKeyDown(Config.Bindings["Convert"]) && ScreenManager.Screens.Peek().GetType().Name == "SongSelection") { converting = true; IBeatmapConverter converter; Config.Reload(); string convertFrom = Config.Get["Converting"]["Game"]; string toConvert = Config.Get["Converting"]["Path"]; // What extension to check for string extension; switch (convertFrom.ToLower()) { case "mania": converter = new ManiaToPulsarc(); extension = "*.osu"; break; default: converter = new IntralismToPulsarc(); extension = "config.txt"; break; } // Get all subfolder names string[] directories = Directory.GetDirectories(toConvert); // If there is no maps in this folder, and the number of sub-folders is 2 or more, // do a Batch Convert if (Directory.GetFiles(toConvert, extension).Length == 0 && directories.Length >= 2) { for (int i = 0; i < directories.Length; i++) { try { converter.Save(directories[i]); } catch { PulsarcLogger.Warning($"Couldn't convert {directories[i]}"); } } } // Otherwise convert one map else { try { converter.Save(toConvert); } catch { PulsarcLogger.Warning($"Couldn't convert {toConvert}"); } } ((SongSelection)ScreenManager.Screens.Peek()).RescanBeatmaps(); } else if (converting && Keyboard.GetState().IsKeyUp(Config.Bindings["Convert"])) { converting = false; } }