### Installing Funkin's Lime Fork Source: https://github.com/funkincrew/funkin/blob/main/docs/TROUBLESHOOTING.md Ensures the correct version of Lime is installed for the Funkin project, addressing segmentation faults or crashes after time change mapping. It uses the 'hmm' package manager to reinstall Lime. ```bash hmm reinstall -f lime ``` -------------------------------- ### Cloning Repository Correctly Source: https://github.com/funkincrew/funkin/blob/main/docs/TROUBLESHOOTING.md Instructs users on how to correctly clone the repository when the 'assets' folder is missing or empty. It involves navigating to the Funkin folder and following the compilation guide from Step 4. ```bash cd the\path\you\copied ``` -------------------------------- ### Haxe Code Comment Examples Source: https://github.com/funkincrew/funkin/blob/main/docs/CONTRIBUTING.md Examples demonstrating both poor and good practices for commenting Haxe code within the Funkin project. These snippets illustrate the importance of clarity, relevance, and professional tone in code documentation. ```haxe function changeSection(sections:Int):Void { var targetTimeSteps:Float = Conductor.instance.currentStepTime + (Conductor.instance.stepsPerMeasure * sections); var targetTimeMs:Float = Conductor.instance.getStepTimeInMs(targetTimeSteps); targetTimeMs = Math.max(0, targetTimeMs); if (FlxG.sound.music != null) { FlxG.sound.music.time = targetTimeMs; } handleSkippedNotes(); SongEventRegistry.handleSkippedEvents(songEvents, Conductor.instance.songPosition); Conductor.instance.update(FlxG.sound?.music?.time ?? 0.0); resyncVocals(); } ``` ```haxe FlxG.sound.music.onComplete = function() { endSong(skipEndingTransition); }; FlxG.sound.music.play(true, Math.max(0, startTimestamp - Conductor.instance.combinedOffset)); FlxG.sound.music.pitch = playbackRate; FlxG.sound.music.volume = 1.0; if (FlxG.sound.music.fadeTween != null) FlxG.sound.music.fadeTween.cancel(); trace('Playing vocals...'); add(vocals); vocals.play(); vocals.volume = 1.0; vocals.pitch = playbackRate; vocals.time = FlxG.sound.music.time; resyncVocals(); ``` ```haxe #if FEATURE_DEBUG_FUNCTIONS if (FlxG.keys.justPressed.PAGEUP) changeSection(FlxG.keys.pressed.SHIFT ? 20 : 2); if (FlxG.keys.justPressed.PAGEDOWN) changeSection(FlxG.keys.pressed.SHIFT ? -20 : -2); #end ``` -------------------------------- ### Build and Compile Friday Night Funkin' Source: https://context7.com/funkincrew/funkin/llms.txt Commands to clone the repository, install dependencies via Haxe Module Manager (hmm), and compile the game for various platforms using Lime. ```bash git clone https://github.com/FunkinCrew/funkin.git cd funkin git submodule update --init --recursive haxelib --global install hmm haxelib --global run hmm setup hmm install haxelib run lime setup lime test windows lime test mac lime test linux lime test html5 lime test windows -debug lime test windows -DFEATURE_POLYMOD_MODS lime test windows -DFEATURE_DISCORD_RPC lime test windows -DFEATURE_VIDEO_PLAYBACK lime test windows -DGITHUB_BUILD ``` -------------------------------- ### Modding with Polymod Source: https://context7.com/funkincrew/funkin/llms.txt Explains how to use the Polymod system for modding, including loading mods, managing installed mods, and hot-reloading assets. ```APIDOC ## Modding with Polymod The game uses Polymod for its modding system, allowing mods to replace assets, add new content, and extend gameplay through scripts. ```haxe // Load all available mods PolymodHandler.loadAllMods(); // Load only enabled mods from save data PolymodHandler.loadEnabledMods(); // Load with no mods PolymodHandler.loadNoMods(); // Get list of all installed mods var allMods:Array = PolymodHandler.getAllMods(); for (mod in allMods) { trace('Mod: ${mod.title} v${mod.modVersion} [${mod.id}]'); trace(' Directory: ${mod.dirName}'); } // Get enabled mods var enabledMods:Array = PolymodHandler.getEnabledMods(); // Check which mods are loaded var loadedModIds:Array = PolymodHandler.loadedModIds; var loadedModDirs:Array = PolymodHandler.loadedModDirs; // Hot reload assets and scripts (debug feature) PolymodHandler.forceReloadAssets(); // API version compatibility var apiVersion:String = PolymodHandler.API_VERSION; // Current game version var versionRule:String = PolymodHandler.API_VERSION_RULE; // ">=0.8.0 <0.9.0" ``` ``` -------------------------------- ### Example -metadata.json Structure Source: https://github.com/funkincrew/funkin/blob/main/docs/FNFC-SPEC.md This JSON file defines the metadata for a song, including its name, artist, timing information, play data, and variations. It serves as the primary configuration for a song's presentation and gameplay. ```json { "version": "2.2.2", "songName": "DadBattle", "artist": "Kawai Sprite", "timeFormat": "ms", "timeChanges": [ { "t": 0, "bpm": 180 } ], "playData": { "album": "volume1", "previewStart": 0, "previewEnd": 15000, "ratings": { "easy": 1, "normal": 3, "hard": 5 }, "songVariations": [ "erect" ], "difficulties": [ "easy", "normal", "hard" ], "characters": { "player": "bf", "girlfriend": "gf", "opponent": "dad" }, "stage": "mainStage", "noteStyle": "funkin" }, "generatedBy": "EliteMasterEric (by hand)" } ``` -------------------------------- ### Rebuilding Lime for Linux Source: https://github.com/funkincrew/funkin/blob/main/docs/TROUBLESHOOTING.md Provides commands to fix 'Uncaught exception - Could not find lime.ndll.' on Linux by recompiling the C++ target for Lime. It includes submodule updates, dependency installation, and the final rebuild command. ```bash cd .haxelib/lime/git git submodule init git submodule sync git submodule update cd ../../.. sudo apt install libgl1-mesa-dev libglu1-mesa-dev g++ g++-multilib gcc-multilib libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev lime rebuild cpp -64 -release -clean ``` -------------------------------- ### Resetting Haxelib Cache Source: https://github.com/funkincrew/funkin/blob/main/docs/TROUBLESHOOTING.md Provides a solution for compilation issues caused by bad library versions. It involves deleting the '.haxelib' folder and restarting the compilation process from Step 5 of the guide. ```bash rm -rf .haxelib ``` -------------------------------- ### Change Song Section (Haxe) Source: https://github.com/funkincrew/funkin/blob/main/docs/CONTRIBUTING.md Allows jumping forward or backward in a song, accounting for BPM changes. It does not prevent death from skipped notes and ensures the time does not go before the song starts. Dependencies include Conductor and FlxG. ```Haxe /** * Jumps forward or backward a number of sections in the song. * Accounts for BPM changes, does not prevent death from skipped notes. * @param sections The number of sections to jump, negative to go backwards. */ function changeSection(sections:Int):Void { var targetTimeSteps:Float = Conductor.instance.currentStepTime + (Conductor.instance.stepsPerMeasure * sections); var targetTimeMs:Float = Conductor.instance.getStepTimeInMs(targetTimeSteps); // Don't go back in time to before the song started. targetTimeMs = Math.max(0, targetTimeMs); if (FlxG.sound.music != null) { FlxG.sound.music.time = targetTimeMs; } handleSkippedNotes(); SongEventRegistry.handleSkippedEvents(songEvents, Conductor.instance.songPosition); Conductor.instance.update(FlxG.sound?.music?.time ?? 0.0); resyncVocals(); } ``` -------------------------------- ### Managing Gameplay with PlayState Source: https://context7.com/funkincrew/funkin/llms.txt Demonstrates how to access the PlayState instance, configure gameplay parameters, and manipulate game state variables such as health, score, and audio settings. ```haxe var playState = PlayState.instance; var params:PlayStateParams = { targetSong: SongRegistry.instance.fetchEntry("bopeebo"), targetDifficulty: "hard", targetVariation: "default", practiceMode: false, botPlayMode: false, startTimestamp: 0.0, playbackRate: 1.0, mirrored: false }; var currentHealth:Float = playState.health; var currentScore:Float = playState.songScore; playState.instrumentalVolume = 0.8; playState.playbackRate = 1.5; playState.needsReset = true; ``` -------------------------------- ### Initialize Song Metadata and Chart Data Source: https://context7.com/funkincrew/funkin/llms.txt Demonstrates how to instantiate song metadata, configure BPM time changes, set play data, and define chart notes and events in Haxe. This structure is essential for defining gameplay parameters and serializing song data to JSON. ```haxe var metadata = new SongMetadata("My Song", "Artist Name", "CharterName"); metadata.timeFormat = SongTimeFormat.MILLISECONDS; metadata.timeChanges = [ new SongTimeChange(0, 120, 4, 4), new SongTimeChange(60000, 140, 4, 4) ]; metadata.playData = new SongPlayData(); metadata.playData.characters = new SongCharacterData("bf", "gf", "dad"); var jsonOutput:String = metadata.serialize(true); var chartData = new SongChartData(); chartData.notes = ["hard" => [new SongNoteData(1000, 0, 0, "")]]; chartData.events = [new SongEventData(5000, "FocusCamera", {char: 1})]; ``` -------------------------------- ### Creating Scripted Modules in Haxe Source: https://context7.com/funkincrew/funkin/llms.txt Demonstrates how to create custom modules by extending the `Module` class. It covers event handling for various game states like module creation, updates, note hits/misses, song events, and game state changes. Modules can hook into gameplay without altering core files. ```Haxe class MyModule extends Module { public function new() { super("my-module", 1000); // moduleId, priority } // Called when module is created (before title screen) override public function onCreate(event:ScriptEvent) { trace("MyModule created!"); } // Called every frame override public function onUpdate(event:UpdateScriptEvent) { var elapsed:Float = event.elapsed; // Update logic here } // Called when a note is hit override public function onNoteHit(event:HitNoteScriptEvent) { var note = event.note; var timing:Float = event.timing; var judgement:String = event.judgement; trace('Hit ${note.noteDirection} with ${judgement}!'); } // Called when a note is missed override public function onNoteMiss(event:NoteScriptEvent) { trace('Missed note!'); } // Called when a hold note is dropped override public function onNoteHoldDrop(event:HoldNoteScriptEvent) { trace('Dropped hold note!'); } // Called on every beat override public function onBeatHit(event:SongTimeScriptEvent) { var beat:Int = event.beat; trace('Beat ${beat}'); } // Called on every step (1/4 of a beat) override public function onStepHit(event:SongTimeScriptEvent) { var step:Int = event.step; } // Called when song countdown begins override public function onCountdownStart(event:CountdownScriptEvent) { trace("Countdown starting!"); } // Called for each countdown tick (3, 2, 1, GO!) override public function onCountdownStep(event:CountdownScriptEvent) { var step:Int = event.step; trace('Countdown: ${step}'); } // Called when song starts playing override public function onSongStart(event:ScriptEvent) { trace("Song started!"); } // Called when song ends override public function onSongEnd(event:ScriptEvent) { trace("Song ended!"); } // Called when player dies override public function onGameOver(event:ScriptEvent) { trace("Game over!"); } // Called when game state changes override public function onStateChangeBegin(event:StateChangeScriptEvent) { var newState = event.targetState; trace('Switching to ${newState}'); } // Cancel events to prevent default behavior override public function onNoteMiss(event:NoteScriptEvent) { if (someCondition) { event.cancel(); // Prevent miss from counting } } } ``` -------------------------------- ### Accessing Assets via Registry System Source: https://context7.com/funkincrew/funkin/llms.txt Shows how to interact with various registry classes to load, cache, and retrieve game data like songs, stages, and character metadata from JSON files. ```haxe var songRegistry = SongRegistry.instance; songRegistry.loadEntries(); var song:Song = songRegistry.fetchEntry("dadbattle"); var stageRegistry = StageRegistry.instance; var stage:Stage = stageRegistry.fetchEntry("mainStage"); CharacterDataParser.loadCharacterCache(); var charData = CharacterDataParser.fetchCharacter("bf"); var isModded:Bool = songRegistry.isScriptedEntry("custom-song"); ``` -------------------------------- ### Documentation PR Guidelines Source: https://github.com/funkincrew/funkin/blob/main/docs/CONTRIBUTING.md Provides guidelines on how to create documentation-based pull requests, focusing on fixing typos and adding information to markdown files. It emphasizes clarity, consistency, and warns against modifying the LICENSE.md file. ```Markdown ## Documentation PRs Documentation-based PRs make changes such as **fixing typos** or **adding new information** in documentation files. This involves modifying one or several of the repository’s `.md` files, found throughout the repository. Make sure your changes are easy to understand and formatted consistently to maximize clarity and readability. > [!CAUTION] > DO NOT TOUCH THE `LICENSE.md` FILE, EVEN TO MAKE SMALL CHANGES! ### Example Documentation PR #### DO NOT: ``` // The original documentation - `F2`: ***OVERLAY***: Enables the Flixel debug overlay, which has partial support for scripting. - `F3`: ***SCREENSHOT***: Takes a screenshot of the game and saves it to the local `screenshots` directory. Works outside of debug builds too! - `F4`: ***EJECT***: Forcibly switch state to the Main Menu (with no extra transition). Useful if you're stuck in a level and you need to get out! - `F5`: ***HOT RELOAD***: Forcibly reload the game's scripts and data files, then restart the current state. If any files in the `assets` folder have been modified, the game should process the changes for you! NOTE: Known bug, this does not reset song charts or song scripts, but it should reset everything else (such as stage layout data and character animation data). - `CTRL-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace. // The new PR additions - `ctrl alt shift e`: No idea what this does - `alt-f4`: closes the game ``` #### DO: ``` // The original documentation - `F2`: ***OVERLAY***: Enables the Flixel debug overlay, which has partial support for scripting. - `F3`: ***SCREENSHOT***: Takes a screenshot of the game and saves it to the local `screenshots` directory. Works outside of debug builds too! - `F4`: ***EJECT***: Forcibly switch state to the Main Menu (with no extra transition). Useful if you're stuck in a level and you need to get out! - `F5`: ***HOT RELOAD***: Forcibly reload the game's scripts and data files, then restart the current state. If any files in the `assets` folder have been modified, the game should process the changes for you! NOTE: Known bug, this does not reset song charts or song scripts, but it should reset everything else (such as stage layout data and character animation data). - `CTRL-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace. // The new PR additions - `CTRL-ALT-SHIFT-E`: ***DUMP SAVE DATA***: Prompts the user to save their save data as a JSON file, so its contents can be viewed. Only available on debug builds. - `ALT-F4`: ***CLOSE GAME***: Closes the game forcibly on Windows. ``` ``` -------------------------------- ### Audio Playback and Volume Control (Haxe) Source: https://github.com/funkincrew/funkin/blob/main/docs/CONTRIBUTING.md Handles the completion of music playback, initiates song ending, and manages audio playback properties such as timestamp, pitch, and volume. It also includes logic for fading and playing vocals. ```Haxe FlxG.sound.music.onComplete = function() { endSong(skipEndingTransition); }; // A negative instrumental offset means the song skips the first few milliseconds of the track. // This just gets added into the startTimestamp behavior so we don't need to do anything extra. FlxG.sound.music.play(true, Math.max(0, startTimestamp - Conductor.instance.combinedOffset)); FlxG.sound.music.pitch = playbackRate; // Prevent the volume from being wrong. FlxG.sound.music.volume = 1.0; if (FlxG.sound.music.fadeTween != null) FlxG.sound.music.fadeTween.cancel(); trace('Playing vocals...'); add(vocals); vocals.play(); vocals.volume = 1.0; vocals.pitch = playbackRate; vocals.time = FlxG.sound.music.time; resyncVocals(); ``` -------------------------------- ### JavaDoc-Style Comments for Public Functions (Haxe) Source: https://github.com/funkincrew/funkin/blob/main/docs/style-guide.md Demonstrates the use of JavaDoc-style comments for public functions in Haxe, as supported by the CodeDox VSCode extension. This practice clarifies function usage, parameters, and return values. ```Haxe /** * Finds the largest deviation from the desired time inside this VoicesGroup. * * @param targetTime The time to check against. * ``` -------------------------------- ### Define FNFC Song Metadata and Manifest Source: https://context7.com/funkincrew/funkin/llms.txt Shows the structure of manifest.json and song metadata files within an FNFC package. These files define song versioning, artist information, BPM, and gameplay character settings. ```json { "version": "1.0.0", "songId": "mysong" } { "version": "2.2.2", "songName": "My Song", "artist": "Artist Name", "charter": "Charter Name", "timeChanges": [{ "t": 0, "bpm": 120, "n": 4, "d": 4 }], "playData": { "difficulties": ["easy", "normal", "hard"], "characters": { "player": "bf", "girlfriend": "gf", "opponent": "dad" } } } ``` -------------------------------- ### Manage Game Save Data with Haxe Source: https://context7.com/funkincrew/funkin/llms.txt Demonstrates how to access the Save instance, perform load/flush operations, retrieve song scores, and manage user options or unlocks. This API is essential for persistent game state management. ```haxe var save = Save.instance; Save.load(); save.flush(); var options = save.options; var songScore = save.getSongScore("bopeebo", "hard"); if (songScore != null) { trace('Score: ${songScore.score}'); } Save.clearData(); ``` -------------------------------- ### Debug Input Handling for Section Skipping (Haxe) Source: https://github.com/funkincrew/funkin/blob/main/docs/CONTRIBUTING.md Implements keyboard shortcuts for skipping song sections forward and backward, with modifier keys (SHIFT) to increase the skip amount. This functionality is conditionally compiled under FEATURE_DEBUG_FUNCTIONS. ```Haxe #if FEATURE_DEBUG_FUNCTIONS // PAGEUP: Skip forward two sections. // SHIFT+PAGEUP: Skip forward twenty sections. if (FlxG.keys.justPressed.PAGEUP) changeSection(FlxG.keys.pressed.SHIFT ? 20 : 2); // PAGEDOWN: Skip backward two section. Doesn't replace notes. // SHIFT+PAGEDOWN: Skip backward twenty sections. if (FlxG.keys.justPressed.PAGEDOWN) changeSection(FlxG.keys.pressed.SHIFT ? -20 : -2); #end ``` -------------------------------- ### Mod Structure (_polymod_meta.json) Source: https://context7.com/funkincrew/funkin/llms.txt Details the required structure for a mod, including the `_polymod_meta.json` file for metadata, versioning, and dependencies. ```APIDOC ## Mod Structure (_polymod_meta.json) Mods are structured as folders with metadata and asset overrides. ```json { "title": "My Custom Mod", "description": "A description of what this mod does.", "contributors": [ { "name": "ModAuthor", "role": "Creator" } ], "api_version": "0.8.0", "mod_version": "1.0.0", "license": "Apache-2.0", "dependencies": { "other-mod": ">=1.0.0" } } ``` ``` -------------------------------- ### Module Handler API in Haxe Source: https://context7.com/funkincrew/funkin/llms.txt Provides functions for managing scripted modules within the game. It allows loading modules from cache, retrieving specific modules by ID, activating/deactivating them at runtime, and dispatching global events to all active modules. It also includes functions to manually trigger module creation and clear the module cache. ```Haxe // Load all modules from mods ModuleHandler.loadModuleCache(); // Get a specific module by ID var module:Module = ModuleHandler.getModule("my-module"); // Activate/deactivate modules at runtime ModuleHandler.activateModule("my-module"); ModuleHandler.deactivateModule("my-module"); // Dispatch events to all active modules var event = new ScriptEvent(ScriptEventType.CREATE, false); ModuleHandler.callEvent(event); // Call onCreate on all modules ModuleHandler.callOnCreate(); // Clear module cache (triggers onDestroy) ModuleHandler.clearModuleCache(); ``` -------------------------------- ### Manage Game Mods with Polymod Source: https://context7.com/funkincrew/funkin/llms.txt Provides methods to load, list, and verify mods using the PolymodHandler. These functions allow developers to manage mod states and check API compatibility. ```haxe PolymodHandler.loadAllMods(); var allMods:Array = PolymodHandler.getAllMods(); for (mod in allMods) { trace('Mod: ${mod.title} v${mod.modVersion} [${mod.id}]'); } PolymodHandler.forceReloadAssets(); ``` -------------------------------- ### Scoring System in Haxe Source: https://context7.com/funkincrew/funkin/llms.txt Details the game's scoring system, focusing on the default PBOT1 system. It includes functions to score notes based on timing, determine the judgement (e.g., 'sick', 'good'), and calculate miss penalties. Constants for scoring thresholds and available scoring systems are also provided. ```Haxe // Score a note based on timing var msTiming:Float = 25.0; // 25ms off from perfect var score:Int = Scoring.scoreNote(msTiming, ScoringSystem.PBOT1); // Get judgement for timing var judgement:String = Scoring.judgeNote(msTiming, ScoringSystem.PBOT1); // Returns: "killer", "sick", "good", "bad", "shit", or "miss" // Get miss penalty score var missScore:Int = Scoring.getMissScore(ScoringSystem.PBOT1); // -100 // PBOT1 Scoring thresholds // Perfect (Killer): 0-12.5ms -> 500 points // Sick: 12.5-45ms -> ~490-350 points // Good: 45-90ms -> ~350-150 points // Bad: 90-135ms -> ~150-50 points // Shit: 135-160ms -> ~50-9 points // Miss: >160ms -> -100 points // Scoring constants var maxScore:Int = Scoring.PBOT1_MAX_SCORE; // 500 var missThreshold:Float = Scoring.PBOT1_MISS_THRESHOLD; // 160ms var killerThreshold:Float = Scoring.PBOT1_KILLER_THRESHOLD; // 12.5ms var sickThreshold:Float = Scoring.PBOT1_SICK_THRESHOLD; // 45ms var goodThreshold:Float = Scoring.PBOT1_GOOD_THRESHOLD; // 90ms var badThreshold:Float = Scoring.PBOT1_BAD_THRESHOLD; // 135ms // Available scoring systems var systems = [ ScoringSystem.LEGACY, // Pre-Week 6 scoring ScoringSystem.WEEK7, // Week 7 tighter windows ScoringSystem.PBOT1 // Current sigmoid-based system ]; ``` -------------------------------- ### Song Data Structures Source: https://context7.com/funkincrew/funkin/llms.txt Defines the structures for song metadata and chart data, including configuration for playback, time changes, notes, and events. ```APIDOC ## Song Data Structures Song data is split between metadata (display info) and chart data (gameplay). These structures define how songs are stored and loaded. ```haxe // Create new song metadata var metadata = new SongMetadata("My Song", "Artist Name", "CharterName"); metadata.timeFormat = SongTimeFormat.MILLISECONDS; metadata.looped = false; // Set up time changes (BPM) metadata.timeChanges = [ new SongTimeChange(0, 120, 4, 4), // 120 BPM, 4/4 time at start new SongTimeChange(60000, 140, 4, 4) // 140 BPM at 60 seconds ]; // Configure play data metadata.playData = new SongPlayData(); metadata.playData.stage = "mainStage"; metadata.playData.noteStyle = "funkin"; metadata.playData.difficulties = ["easy", "normal", "hard"]; metadata.playData.songVariations = ["erect"]; // Alternative variations metadata.playData.album = "volume1"; metadata.playData.previewStart = 0.0; metadata.playData.previewEnd = 15000.0; metadata.playData.ratings = [ "easy" => 1, "normal" => 3, "hard" => 5 ]; // Set up characters metadata.playData.characters = new SongCharacterData("bf", "gf", "dad"); // Configure offsets metadata.offsets = new SongOffsets(); metadata.offsets.instrumental = 0.0; // Serialize to JSON var jsonOutput:String = metadata.serialize(true); // Create chart data with notes var chartData = new SongChartData(); chartData.scrollSpeed = ["easy" => 1.0, "normal" => 1.2, "hard" => 1.5]; // Add notes to chart var notes:Array = [ new SongNoteData(1000, 0, 0, ""), // Note at 1s, direction 0, no sustain new SongNoteData(1500, 1, 500, ""), // Note at 1.5s, direction 1, 500ms hold new SongNoteData(2000, 2, 0, "mine") // Mine note at 2s ]; chartData.notes = ["hard" => notes]; // Add song events var events:Array = [ new SongEventData(5000, "FocusCamera", {char: 1}), new SongEventData(10000, "ZoomCamera", {zoom: 1.2, duration: 1.0}) ]; chartData.events = events; ``` ``` -------------------------------- ### Manage Musical Timing with Conductor API Source: https://context7.com/funkincrew/funkin/llms.txt The Conductor class manages BPM, time signatures, and beat/step callbacks. It allows developers to synchronize game logic with the music by converting between time units and tracking song progression. ```haxe var conductor = Conductor.instance; conductor.update(FlxG.sound.music.time); var currentBPM:Float = conductor.bpm; var currentBeat:Int = conductor.currentBeat; var currentStep:Int = conductor.currentStep; var currentMeasure:Int = conductor.currentMeasure; var beatTime:Float = conductor.currentBeatTime; var stepTime:Float = conductor.currentStepTime; conductor.forceBPM(150.0); conductor.forceBPM(null); var timeChanges:Array = [ new SongTimeChange(0, 120), new SongTimeChange(30000, 150) ]; conductor.mapTimeChanges(timeChanges); var msTime:Float = conductor.getStepTimeInMs(64.0); var stepTime:Float = conductor.getTimeInSteps(15000.0); var beatMs:Float = conductor.getBeatTimeInMs(16.0); var measureMs:Float = conductor.getMeasureTimeInMs(4.0); Conductor.beatHit.add(function() { trace('Beat hit: ${Conductor.instance.currentBeat}'); }); Conductor.stepHit.add(function() { trace('Step hit: ${Conductor.instance.currentStep}'); }); Conductor.measureHit.add(function() { trace('Measure hit: ${Conductor.instance.currentMeasure}'); }); var beatLength:Float = conductor.beatLengthMs; var stepLength:Float = conductor.stepLengthMs; var measureLength:Float = conductor.measureLengthMs; var numerator:Int = conductor.timeSignatureNumerator; var denominator:Int = conductor.timeSignatureDenominator; var beatsPerMeasure:Float = conductor.beatsPerMeasure; var stepsPerMeasure:Int = conductor.stepsPerMeasure; ``` -------------------------------- ### Define Mod Metadata Structure Source: https://context7.com/funkincrew/funkin/llms.txt The required JSON format for the _polymod_meta.json file. This file provides critical information about the mod, including versioning, license, and dependencies. ```json { "title": "My Custom Mod", "description": "A description of what this mod does.", "contributors": [ { "name": "ModAuthor", "role": "Creator" } ], "api_version": "0.8.0", "mod_version": "1.0.0", "license": "Apache-2.0", "dependencies": { "other-mod": ">=1.0.0" } } ``` -------------------------------- ### Manifest JSON Structure Source: https://github.com/funkincrew/funkin/blob/main/docs/FNFC-SPEC.md Defines the structure of the manifest.json file, which contains essential information for identifying a chart. It includes the manifest version and a unique song ID. ```json { "version": "1.0.0", "songId": "dadbattle" } ``` -------------------------------- ### Fixing Git RPC Failed Error Source: https://github.com/funkincrew/funkin/blob/main/docs/TROUBLESHOOTING.md Resolves 'error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)' during Git cloning, often caused by poor network connectivity. This command increases the HTTP post buffer size. ```bash git config --global http.postBuffer 4096M ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.