diff --git a/.vscode/settings.json b/.vscode/settings.json index af5986fbf..793f2997f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -111,6 +111,11 @@ "target": "hl", "args": ["-debug"] }, + { + "label": "Windows / Debug (Discord)", + "target": "windows", + "args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS", "-DFEATURE_DISCORD_RPC"] + }, { "label": "Windows / Debug (FlxAnimate Test)", "target": "windows", diff --git a/art b/art index 1f64f3e74..fbd3e3df7 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 1f64f3e7403a090b164f4442d10152b2be5d3d0a +Subproject commit fbd3e3df77734606d88516770b71b56e6fa04bce diff --git a/hmm.json b/hmm.json index 7c8959e91..0c0c5571b 100644 --- a/hmm.json +++ b/hmm.json @@ -7,13 +7,6 @@ "ref": "a1eab7b9bf507b87200a3341719054fe427f3b15", "url": "https://github.com/FunkinCrew/FlxPartialSound.git" }, - { - "name": "discord_rpc", - "type": "git", - "dir": null, - "ref": "2d83fa863ef0c1eace5f1cf67c3ac315d1a3a8a5", - "url": "https://github.com/FunkinCrew/linc_discord-rpc" - }, { "name": "flixel", "type": "git", @@ -108,6 +101,13 @@ "ref": "147294123f983e35f50a966741474438069a7a8f", "url": "https://github.com/FunkinCrew/hxcpp-debugger" }, + { + "name": "hxdiscord_rpc", + "type": "git", + "dir": null, + "ref": "82c47ecc1a454b7dd644e4fcac7e91155f176dec", + "url": "https://github.com/FunkinCrew/hxdiscord_rpc" + }, { "name": "hxjsonast", "type": "git", diff --git a/project.hxp b/project.hxp index eaabf9d30..2f537935a 100644 --- a/project.hxp +++ b/project.hxp @@ -479,10 +479,9 @@ class Project extends HXProject { // Should default to true on workspace builds and false on release builds. REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop()); - // Should be true on release, non-tester builds. + // Should be true on desktop, release, non-tester builds. // We don't want testers to accidentally leak songs to their Discord friends! - // TODO: Re-enable this. - FEATURE_DISCORD_RPC.apply(this, false && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this)); + FEATURE_DISCORD_RPC.apply(this, isDesktop() && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this)); // Should be true only on web builds. // Audio context issues only exist there. @@ -654,7 +653,7 @@ class Project extends HXProject { } if (FEATURE_DISCORD_RPC.isEnabled(this)) { - addHaxelib('discord_rpc'); // Discord API + addHaxelib('hxdiscord_rpc'); // Discord API } if (FEATURE_NEWGROUNDS.isEnabled(this)) { diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 30a6d253a..a0ca74162 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -1,42 +1,42 @@ package funkin; -import funkin.data.freeplay.player.PlayerRegistry; -import funkin.ui.debug.charting.ChartEditorState; -import funkin.ui.transition.LoadingState; -import flixel.FlxState; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond; import flixel.addons.transition.TransitionData; +import flixel.FlxSprite; +import flixel.FlxState; import flixel.graphics.FlxGraphic; import flixel.math.FlxPoint; import flixel.math.FlxRect; -import flixel.FlxSprite; import flixel.system.debug.log.LogStyle; import flixel.util.FlxColor; -import funkin.util.macro.MacroUtil; -import funkin.util.WindowUtil; -import funkin.play.PlayStatePlaylist; -import openfl.display.BitmapData; -import funkin.data.story.level.LevelRegistry; -import funkin.data.notestyle.NoteStyleRegistry; -import funkin.data.freeplay.style.FreeplayStyleRegistry; -import funkin.data.event.SongEventRegistry; -import funkin.data.stage.StageRegistry; import funkin.data.dialogue.conversation.ConversationRegistry; import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry; import funkin.data.dialogue.speaker.SpeakerRegistry; import funkin.data.freeplay.album.AlbumRegistry; +import funkin.data.freeplay.player.PlayerRegistry; +import funkin.data.freeplay.style.FreeplayStyleRegistry; +import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.song.SongRegistry; +import funkin.data.event.SongEventRegistry; +import funkin.data.stage.StageRegistry; +import funkin.data.story.level.LevelRegistry; +import funkin.modding.module.ModuleHandler; import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.notes.notekind.NoteKindManager; -import funkin.modding.module.ModuleHandler; +import funkin.play.PlayStatePlaylist; +import funkin.ui.debug.charting.ChartEditorState; import funkin.ui.title.TitleState; +import funkin.ui.transition.LoadingState; import funkin.util.CLIUtil; import funkin.util.CLIUtil.CLIParams; +import funkin.util.macro.MacroUtil; import funkin.util.TimerUtil; import funkin.util.TrackerUtil; +import funkin.util.WindowUtil; +import openfl.display.BitmapData; #if FEATURE_DISCORD_RPC -import Discord.DiscordClient; +import funkin.api.discord.DiscordClient; #end /** @@ -125,10 +125,10 @@ class InitState extends FlxState // DISCORD API SETUP // #if FEATURE_DISCORD_RPC - DiscordClient.initialize(); + DiscordClient.instance.init(); - Application.current.onExit.add(function(exitCode) { - DiscordClient.shutdown(); + lime.app.Application.current.onExit.add(function(exitCode) { + DiscordClient.instance.shutdown(); }); #end diff --git a/source/funkin/api/discord/Discord.hx b/source/funkin/api/discord/Discord.hx deleted file mode 100644 index 9dd513bf7..000000000 --- a/source/funkin/api/discord/Discord.hx +++ /dev/null @@ -1,91 +0,0 @@ -package funkin.api.discord; - -import Sys.sleep; -#if FEATURE_DISCORD_RPC -import discord_rpc.DiscordRpc; -#end - -class DiscordClient -{ - #if FEATURE_DISCORD_RPC - public function new() - { - trace("Discord Client starting..."); - DiscordRpc.start( - { - clientID: "814588678700924999", - onReady: onReady, - onError: onError, - onDisconnected: onDisconnected - }); - trace("Discord Client started."); - - while (true) - { - DiscordRpc.process(); - sleep(2); - // trace("Discord Client Update"); - } - - DiscordRpc.shutdown(); - } - - public static function shutdown() - { - DiscordRpc.shutdown(); - } - - static function onReady() - { - DiscordRpc.presence( - { - details: "In the Menus", - state: null, - largeImageKey: 'icon', - largeImageText: "Friday Night Funkin'" - }); - } - - static function onError(_code:Int, _message:String) - { - trace('Error! $_code : $_message'); - } - - static function onDisconnected(_code:Int, _message:String) - { - trace('Disconnected! $_code : $_message'); - } - - public static function initialize() - { - var DiscordDaemon = sys.thread.Thread.create(() -> { - new DiscordClient(); - }); - trace("Discord Client initialized"); - } - - public static function changePresence(details:String, ?state:String, ?smallImageKey:String, ?hasStartTimestamp:Bool, ?endTimestamp:Float) - { - var startTimestamp:Float = if (hasStartTimestamp) Date.now().getTime() else 0; - - if (endTimestamp > 0) - { - endTimestamp = startTimestamp + endTimestamp; - } - - DiscordRpc.presence( - { - details: details, - state: state, - largeImageKey: 'icon', - largeImageText: "Friday Night Funkin'", - smallImageKey: smallImageKey, - // Obtained times are in milliseconds so they are divided so Discord can use it - startTimestamp: Std.int(startTimestamp / 1000), - endTimestamp: Std.int(endTimestamp / 1000) - }); - - // trace('Discord RPC Updated. Arguments: $details, $state, $smallImageKey, $hasStartTimestamp, $endTimestamp'); - } - #end -} diff --git a/source/funkin/api/discord/DiscordClient.hx b/source/funkin/api/discord/DiscordClient.hx new file mode 100644 index 000000000..3be2d4c87 --- /dev/null +++ b/source/funkin/api/discord/DiscordClient.hx @@ -0,0 +1,204 @@ +package funkin.api.discord; + +#if FEATURE_DISCORD_RPC +import hxdiscord_rpc.Discord; +import hxdiscord_rpc.Types; +import sys.thread.Thread; + +class DiscordClient +{ + static final CLIENT_ID:String = "816168432860790794"; + + public static var instance(get, never):DiscordClient; + static var _instance:Null = null; + + static function get_instance():DiscordClient + { + if (DiscordClient._instance == null) _instance = new DiscordClient(); + if (DiscordClient._instance == null) throw "Could not initialize singleton DiscordClient!"; + return DiscordClient._instance; + } + + var handlers:DiscordEventHandlers; + + private function new() + { + trace('[DISCORD] Initializing event handlers...'); + + handlers = DiscordEventHandlers.create(); + + handlers.ready = cpp.Function.fromStaticFunction(onReady); + handlers.disconnected = cpp.Function.fromStaticFunction(onDisconnected); + handlers.errored = cpp.Function.fromStaticFunction(onError); + } + + public function init():Void + { + trace('[DISCORD] Initializing connection...'); + + // Discord.initialize(CLIENT_ID, handlers, true, null); + Discord.Initialize(CLIENT_ID, cpp.RawPointer.addressOf(handlers), 1, null); + + createDaemon(); + } + + var daemon:Thread = null; + + function createDaemon():Void + { + daemon = Thread.create(doDaemonWork); + } + + function doDaemonWork():Void + { + while (true) + { + trace('[DISCORD] Performing client update...'); + + #if DISCORD_DISABLE_IO_THREAD + Discord.updateConnection(); + #end + + Discord.runCallbacks(); + Sys.sleep(2); + } + } + + public function shutdown():Void + { + trace('[DISCORD] Shutting down...'); + + Discord.shutdown(); + } + + public function setPresence(params:DiscordClientPresenceParams):Void + { + trace('[DISCORD] Updating presence... (${params})'); + + Discord.updatePresence(buildPresence(params)); + } + + function buildPresence(params:DiscordClientPresenceParams):DiscordRichPresence + { + var presence = DiscordRichPresence.create(); + + // Presence should always be playing the game. + presence.type = DiscordActivityType_Playing; + + // Text when hovering over the large image. We just leave this as the game name. + presence.largeImageText = "Friday Night Funkin'"; + + // State should be generally what the person is doing, like "In the Menus" or "Pico (Pico Mix) [Freeplay Hard]" + presence.state = cast(params.state, Null); + // Details should be what the person is specifically doing, including stuff like timestamps (maybe something like "03:24 elapsed"). + presence.details = cast(params.details, Null); + + // The large image displaying what the user is doing. + // This should probably be album art. + // IMPORTANT NOTE: This can be an asset key uploaded to Discord's developer panel OR any URL you like. + presence.largeImageKey = cast(params.largeImageKey, Null) ?? "album-volume1"; + + trace('[DISCORD] largeImageKey: ${presence.largeImageKey}'); + + // TODO: Make this use the song's album art. + // presence.largeImageKey = "icon"; + // presence.largeImageKey = "https://f4.bcbits.com/img/a0746694746_16.jpg"; + + // The small inset image for what the user is doing. + // This can be the opponent's health icon? + // NOTE: Like largeImageKey, this can be a URL, or an asset key. + presence.smallImageKey = cast(params.smallImageKey, Null); + + // NOTE: In previous versions, this showed as "Elapsed", but now shows as playtime and doesn't look good + // presence.startTimestamp = time - 10; + // presence.endTimestamp = time + 30; + + final button1:DiscordButton = DiscordButton.create(); + button1.label = "Play on Web"; + button1.url = Constants.URL_NEWGROUNDS; + presence.buttons[0] = button1; + + final button2:DiscordButton = DiscordButton.create(); + button2.label = "Download"; + button2.url = Constants.URL_ITCH; + presence.buttons[1] = button2; + + return presence; + } + + // TODO: WHAT THE FUCK get this pointer bullfuckery out of here + private static function onReady(request:cpp.RawConstPointer):Void + { + trace('[DISCORD] Client has connected!'); + + final username:String = request[0].username; + final globalName:String = request[0].username; + final discriminator:Int = Std.parseInt(request[0].discriminator); + + if (discriminator != 0) + { + trace('[DISCORD] User: ${username}#${discriminator} (${globalName})'); + } + else + { + trace('[DISCORD] User: @${username} (${globalName})'); + } + } + + private static function onDisconnected(errorCode:Int, message:cpp.ConstCharStar):Void + { + trace('[DISCORD] Client has disconnected! ($errorCode) "${cast (message, String)}"'); + } + + private static function onError(errorCode:Int, message:cpp.ConstCharStar):Void + { + trace('[DISCORD] Client has received an error! ($errorCode) "${cast (message, String)}"'); + } + + // public var type(get, set):DiscordActivityType; + // public var state(get, set):String; + // public var details(get, set):String; + // public var startTimestamp(get, set):Int; + // public var endTimestamp(get, set):Int; + // public var largeImageKey(get, set):String; + // public var largeImageText(get, set):String; + // public var smallImageKey(get, set):String; + // public var smallImageText(get, set):String; + // + // + // public var partyId(get, set) + // public var partySize(get, set) + // public var partyMax(get, set) + // public var partyPrivacy(get, set) + // + // public var buttons(get, set) + // + // public var matchSecret(get, set) + // public var joinSecret(get, set) + // public var spectateSecret(get, set) +} + +typedef DiscordClientPresenceParams = +{ + /** + * The first row of text below the game title. + */ + var state:String; + + /** + * The second row of text below the game title. + * Use `null` to display no text. + */ + var details:Null; + + /** + * A large, 4-row high image to the left of the content. + */ + var ?largeImageKey:String; + + /** + * A small, inset image to the bottom right of `largeImageKey`. + */ + var ?smallImageKey:String; +} +#end diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 081b4e860..fa2b28d54 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -15,8 +15,8 @@ import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.ui.FlxBar; import flixel.util.FlxColor; -import flixel.util.FlxTimer; import flixel.util.FlxStringUtil; +import flixel.util.FlxTimer; import funkin.api.newgrounds.NGio; import funkin.audio.FunkinSound; import funkin.audio.VoicesGroup; @@ -44,12 +44,12 @@ import funkin.play.cutscene.dialogue.Conversation; import funkin.play.cutscene.VanillaCutscenes; import funkin.play.cutscene.VideoCutscene; import funkin.play.notes.NoteDirection; +import funkin.play.notes.notekind.NoteKindManager; import funkin.play.notes.NoteSplash; import funkin.play.notes.NoteSprite; import funkin.play.notes.notestyle.NoteStyle; import funkin.play.notes.Strumline; import funkin.play.notes.SustainTrail; -import funkin.play.notes.notekind.NoteKindManager; import funkin.play.scoring.Scoring; import funkin.play.song.Song; import funkin.play.stage.Stage; @@ -68,7 +68,7 @@ import openfl.display.BitmapData; import openfl.geom.Rectangle; import openfl.Lib; #if FEATURE_DISCORD_RPC -import Discord.DiscordClient; +import funkin.api.discord.DiscordClient; #end /** @@ -447,10 +447,8 @@ class PlayState extends MusicBeatSubState #if FEATURE_DISCORD_RPC // Discord RPC variables - var storyDifficultyText:String = ''; - var iconRPC:String = ''; - var detailsText:String = ''; - var detailsPausedText:String = ''; + var discordRPCAlbum:String = ''; + var discordRPCIcon:String = ''; #end /** @@ -994,7 +992,15 @@ class PlayState extends MusicBeatSubState } #if FEATURE_DISCORD_RPC - DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); + DiscordClient.instance.setPresence( + { + details: 'Paused - ${buildDiscordRPCDetails()}', + + state: buildDiscordRPCState(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); #end } } @@ -1083,8 +1089,14 @@ class PlayState extends MusicBeatSubState } #if FEATURE_DISCORD_RPC - // Game Over doesn't get his own variable because it's only used here - DiscordClient.changePresence('Game Over - ' + detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); + DiscordClient.instance.setPresence( + { + details: 'Game Over - ${buildDiscordRPCDetails()}', + state: buildDiscordRPCState(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); #end } else if (isPlayerDying) @@ -1295,14 +1307,29 @@ class PlayState extends MusicBeatSubState Countdown.resumeCountdown(); #if FEATURE_DISCORD_RPC - if (startTimer.finished) + if (Conductor.instance.songPosition > 0) { - DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true, - currentSongLengthMs - Conductor.instance.songPosition); + // DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true, + // currentSongLengthMs - Conductor.instance.songPosition); + DiscordClient.instance.setPresence( + { + state: buildDiscordRPCState(), + details: buildDiscordRPCDetails(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); } else { - DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC); + DiscordClient.instance.setPresence( + { + state: buildDiscordRPCState(), + details: buildDiscordRPCDetails(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); } #end @@ -1328,16 +1355,32 @@ class PlayState extends MusicBeatSubState #end #if FEATURE_DISCORD_RPC - if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) + if (health > Constants.HEALTH_MIN && !isGamePaused && FlxG.autoPause) { - if (Conductor.instance.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song - + ' (' - + storyDifficultyText - + ')', iconRPC, true, - currentSongLengthMs - - Conductor.instance.songPosition); + if (Conductor.instance.songPosition > 0.0) + { + DiscordClient.instance.setPresence( + { + state: buildDiscordRPCState(), + details: buildDiscordRPCDetails(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); + } else - DiscordClient.changePresence(detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); + { + DiscordClient.instance.setPresence( + { + state: buildDiscordRPCState(), + details: buildDiscordRPCDetails(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); + // DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true, + // currentSongLengthMs - Conductor.instance.songPosition); + } } #end @@ -1354,8 +1397,17 @@ class PlayState extends MusicBeatSubState #end #if FEATURE_DISCORD_RPC - if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText, - currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); + if (health > Constants.HEALTH_MIN && !isGamePaused && FlxG.autoPause) + { + DiscordClient.instance.setPresence( + { + state: buildDiscordRPCState(), + details: buildDiscordRPCDetails(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); + } #end super.onFocusLost(); @@ -1653,6 +1705,11 @@ class PlayState extends MusicBeatSubState iconP2.zIndex = 850; add(iconP2); iconP2.cameras = [camHUD]; + + #if FEATURE_DISCORD_RPC + discordRPCAlbum = 'album-${currentChart.album}'; + discordRPCIcon = 'icon-${currentCharacterData.opponent}'; + #end } // @@ -1768,29 +1825,53 @@ class PlayState extends MusicBeatSubState function initDiscord():Void { #if FEATURE_DISCORD_RPC - storyDifficultyText = difficultyString(); - iconRPC = currentSong.player2; - - // To avoid having duplicate images in Discord assets - switch (iconRPC) - { - case 'senpai-angry': - iconRPC = 'senpai'; - case 'monster-christmas': - iconRPC = 'monster'; - case 'mom-car': - iconRPC = 'mom'; - } - - // String that contains the mode defined here so it isn't necessary to call changePresence for each mode - detailsText = isStoryMode ? 'Story Mode: Week $storyWeek' : 'Freeplay'; - detailsPausedText = 'Paused - $detailsText'; + // Determine the details strings once and reuse them. // Updating Discord Rich Presence. - DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC); + DiscordClient.instance.setPresence( + { + state: buildDiscordRPCState(), + details: buildDiscordRPCDetails(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); #end } + function buildDiscordRPCDetails():String + { + if (PlayStatePlaylist.isStoryMode) + { + return 'Story Mode: ${PlayStatePlaylist.campaignTitle}'; + } + else + { + if (isChartingMode) + { + return 'Chart Editor [Playtest]'; + } + else if (isPracticeMode) + { + return 'Freeplay [Practice]'; + } + else if (isBotPlayMode) + { + return 'Freeplay [Bot Play]'; + } + else + { + return 'Freeplay'; + } + } + } + + function buildDiscordRPCState():String + { + var discordRPCDifficulty = PlayState.instance.currentDifficulty.replace('-', ' ').toTitleCase(); + return '${currentChart.songName} [${discordRPCDifficulty}]'; + } + function initPreciseInputs():Void { PreciseInputManager.instance.onInputPressed.add(onKeyPress); @@ -1985,7 +2066,15 @@ class PlayState extends MusicBeatSubState #if FEATURE_DISCORD_RPC // Updating Discord Rich Presence (with Time Left) - DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true, currentSongLengthMs); + DiscordClient.instance.setPresence( + { + state: buildDiscordRPCState(), + details: buildDiscordRPCDetails(), + + largeImageKey: discordRPCAlbum, + smallImageKey: discordRPCIcon + }); + // DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true, currentSongLengthMs); #end if (startTimestamp > 0) diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index d87aca9f3..94ce4c0ab 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -323,6 +323,11 @@ class BaseCharacter extends Bopper this.cameraFocusPoint = new FlxPoint(charCenterX + _data.cameraOffsets[0], charCenterY + _data.cameraOffsets[1]); } + public function getHealthIconId():String + { + return _data?.healthIcon?.id ?? Constants.DEFAULT_HEALTH_ICON; + } + public function initHealthIcon(isOpponent:Bool):Void { if (!isOpponent) @@ -332,7 +337,7 @@ class BaseCharacter extends Bopper trace('[WARN] Player 1 health icon not found!'); return; } - PlayState.instance.iconP1.configure(_data.healthIcon); + PlayState.instance.iconP1.configure(_data?.healthIcon); PlayState.instance.iconP1.flipX = !PlayState.instance.iconP1.flipX; // BF is looking the other way. } else @@ -342,7 +347,7 @@ class BaseCharacter extends Bopper trace('[WARN] Player 2 health icon not found!'); return; } - PlayState.instance.iconP2.configure(_data.healthIcon); + PlayState.instance.iconP2.configure(_data?.healthIcon); } } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 7f8bfdca7..ba2f24a73 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2274,8 +2274,25 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState this.openBackupAvailableDialog(welcomeDialog); } } + + #if FEATURE_DISCORD_RPC + updateDiscordRPC(); + #end } + #if FEATURE_DISCORD_RPC + function updateDiscordRPC():Void + { + funkin.api.discord.DiscordClient.instance.setPresence( + { + // TODO: Make this display the song name and update when it changes. + // state: '${currentSongName} [${selectedDifficulty}]', + state: null, + details: 'Chart Editor [Charting]' + }); + } + #end + function setupWelcomeMusic() { this.welcomeMusic.loadEmbedded(Paths.music('chartEditorLoop/chartEditorLoop')); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 044b78e22..7d40e8516 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -54,6 +54,9 @@ import funkin.util.SortUtil; import openfl.display.BlendMode; import funkin.data.freeplay.style.FreeplayStyleRegistry; import funkin.data.song.SongData.SongMusicData; +#if FEATURE_DISCORD_RPC +import funkin.api.discord.DiscordClient; +#end /** * Parameters used to initialize the FreeplayState. @@ -338,7 +341,7 @@ class FreeplayState extends MusicBeatSubState #if FEATURE_DISCORD_RPC // Updating Discord Rich Presence - DiscordClient.changePresence('In the Menus', null); + DiscordClient.instance.setPresence({state: 'In the Menus', details: null}); #end var isDebug:Bool = false; diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index ee6abc084..685626cba 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -28,7 +28,7 @@ import funkin.ui.story.StoryMenuState; import funkin.ui.Prompt; import funkin.util.WindowUtil; #if FEATURE_DISCORD_RPC -import Discord.DiscordClient; +import funkin.api.discord.DiscordClient; #end #if newgrounds import funkin.ui.NgPrompt; @@ -55,8 +55,7 @@ class MainMenuState extends MusicBeatState override function create():Void { #if FEATURE_DISCORD_RPC - // Updating Discord Rich Presence - DiscordClient.changePresence("In the Menus", null); + DiscordClient.instance.setPresence({state: "In the Menus", details: null}); #end FlxG.cameras.reset(new FunkinCamera('mainMenu')); diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index c0ed2712a..09af08b22 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -23,6 +23,10 @@ import funkin.ui.MusicBeatState; import funkin.ui.transition.LoadingState; import funkin.ui.transition.StickerSubState; import funkin.util.MathUtil; +import openfl.utils.Assets; +#if FEATURE_DISCORD_RPC +import funkin.api.discord.DiscordClient; +#end class StoryMenuState extends MusicBeatState { @@ -217,7 +221,7 @@ class StoryMenuState extends MusicBeatState #if FEATURE_DISCORD_RPC // Updating Discord Rich Presence - DiscordClient.changePresence('In the Menus', null); + DiscordClient.instance.setPresence({state: 'In the Menus', details: null}); #end } diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 9536a728f..d5bc987e8 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -78,7 +78,12 @@ class Constants /** * Link to download the game on Itch.io. */ - public static final URL_ITCH:String = 'https://ninja-muffin24.itch.io/funkin/purchase'; + public static final URL_ITCH:String = 'https://ninja-muffin24.itch.io/funkin'; + + /** + * Link to play the game on Newgrounds. + */ + public static final URL_NEWGROUNDS:String = 'https://www.newgrounds.com/portal/view/770371'; /** * Link to the game's page on Kickstarter.