diff --git a/Project.xml b/Project.xml index 7edddb77c..08b9a5a47 100644 --- a/Project.xml +++ b/Project.xml @@ -116,6 +116,7 @@ + diff --git a/source/Discord.hx b/source/Discord.hx new file mode 100644 index 000000000..253a4f59a --- /dev/null +++ b/source/Discord.hx @@ -0,0 +1,82 @@ +package; + +import Sys.sleep; +import discord_rpc.DiscordRpc; + +using StringTools; + +class DiscordClient +{ + 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(); + } + + 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:Null, ?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'); + } +} diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index 6dec6f1a6..3949a3d32 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -1,5 +1,8 @@ package; +#if desktop +import Discord.DiscordClient; +#end import flash.text.TextField; import flixel.FlxG; import flixel.FlxSprite; @@ -47,6 +50,11 @@ class FreeplayState extends MusicBeatState } */ + #if desktop + // Updating Discord Rich Presence + DiscordClient.changePresence("In the Menus", null); + #end + var isDebug:Bool = false; #if debug diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 4b3a8f110..35fb50e8a 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -1,5 +1,8 @@ package; +#if desktop +import Discord.DiscordClient; +#end import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; @@ -33,6 +36,11 @@ class MainMenuState extends MusicBeatState override function create() { + #if desktop + // Updating Discord Rich Presence + DiscordClient.changePresence("In the Menus", null); + #end + transIn = FlxTransitionableState.defaultTransIn; transOut = FlxTransitionableState.defaultTransOut; diff --git a/source/PlayState.hx b/source/PlayState.hx index aabb992f5..aa41737ea 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1,5 +1,8 @@ package; +#if desktop +import Discord.DiscordClient; +#end import Section.SwagSection; import Song.SwagSong; import WiggleEffect.WiggleEffectType; @@ -122,9 +125,17 @@ class PlayState extends MusicBeatState var inCutscene:Bool = false; + #if desktop + // Discord RPC variables + var storyDifficultyText:String = ""; + var iconRPC:String = ""; + var songLength:Float = 0; + var detailsText:String = ""; + var detailsPausedText:String = ""; + #end + override public function create() { - if (FlxG.sound.music != null) FlxG.sound.music.stop(); @@ -174,6 +185,48 @@ class PlayState extends MusicBeatState dialogue = CoolUtil.coolTextFile(Paths.txt('thorns/thornsDialogue')); } + #if desktop + // Making difficulty text for Discord Rich Presence. + switch (storyDifficulty) + { + case 0: + storyDifficultyText = "Easy"; + case 1: + storyDifficultyText = "Normal"; + case 2: + storyDifficultyText = "Hard"; + } + + iconRPC = SONG.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 + if (isStoryMode) + { + detailsText = "Story Mode: Week " + storyWeek; + } + else + { + detailsText = "Freeplay"; + } + + // String for when the game is paused + detailsPausedText = "Paused - " + detailsText; + + // Updating Discord Rich Presence. + DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); + #end + if (SONG.song.toLowerCase() == 'spookeez' || SONG.song.toLowerCase() == 'monster' || SONG.song.toLowerCase() == 'south') { curStage = "spooky"; @@ -870,16 +923,8 @@ class PlayState extends MusicBeatState var introAssets:Map> = new Map>(); introAssets.set('default', ['ready', "set", "go"]); - introAssets.set('school', [ - 'weeb/pixelUI/ready-pixel', - 'weeb/pixelUI/set-pixel', - 'weeb/pixelUI/date-pixel' - ]); - introAssets.set('schoolEvil', [ - 'weeb/pixelUI/ready-pixel', - 'weeb/pixelUI/set-pixel', - 'weeb/pixelUI/date-pixel' - ]); + introAssets.set('school', ['weeb/pixelUI/ready-pixel', 'weeb/pixelUI/set-pixel', 'weeb/pixelUI/date-pixel']); + introAssets.set('schoolEvil', ['weeb/pixelUI/ready-pixel', 'weeb/pixelUI/set-pixel', 'weeb/pixelUI/date-pixel']); var introAlts:Array = introAssets.get('default'); var altSuffix:String = ""; @@ -975,6 +1020,14 @@ class PlayState extends MusicBeatState FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); FlxG.sound.music.onComplete = endSong; vocals.play(); + + #if desktop + // Song duration in a float, useful for the time left feature + songLength = FlxG.sound.music.length; + + // Updating Discord Rich Presence (with Time Left) + DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC, true, songLength); + #end } var debugNum:Int = 0; @@ -1059,9 +1112,7 @@ class PlayState extends MusicBeatState { swagNote.x += FlxG.width / 2; // general offset } - else - { - } + else {} } daBeats += 1; } @@ -1217,11 +1268,53 @@ class PlayState extends MusicBeatState if (!startTimer.finished) startTimer.active = true; paused = false; + + #if desktop + if (startTimer.finished) + { + DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC, true, songLength - Conductor.songPosition); + } + else + { + DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); + } + #end } super.closeSubState(); } + override public function onFocus():Void + { + #if desktop + if (health > 0 && !paused) + { + if (Conductor.songPosition > 0.0) + { + DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC, true, songLength - Conductor.songPosition); + } + else + { + DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); + } + } + #end + + super.onFocus(); + } + + override public function onFocusLost():Void + { + #if desktop + if (health > 0 && !paused) + { + DiscordClient.changePresence(detailsPausedText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); + } + #end + + super.onFocusLost(); + } + function resyncVocals():Void { vocals.pause(); @@ -1284,11 +1377,19 @@ class PlayState extends MusicBeatState } else openSubState(new PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + + #if desktop + DiscordClient.changePresence(detailsPausedText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); + #end } if (FlxG.keys.justPressed.SEVEN) { FlxG.switchState(new ChartingState()); + + #if desktop + DiscordClient.changePresence("Chart Editor", null, null, true); + #end } // FlxG.watch.addQuick('VOL', vocals.amplitudeLeft); @@ -1484,6 +1585,11 @@ class PlayState extends MusicBeatState openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + + #if desktop + // Game Over doesn't get his own variable because it's only used here + DiscordClient.changePresence("Game Over - " + detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); + #end } if (unspawnNotes[0] != null) @@ -1920,29 +2026,29 @@ class PlayState extends MusicBeatState */ // trace(daNote.noteData); /* - switch (daNote.noteData) + switch (daNote.noteData) + { + case 2: // NOTES YOU JUST PRESSED + if (upP || rightP || downP || leftP) + noteCheck(upP, daNote); + case 3: + if (upP || rightP || downP || leftP) + noteCheck(rightP, daNote); + case 1: + if (upP || rightP || downP || leftP) + noteCheck(downP, daNote); + case 0: + if (upP || rightP || downP || leftP) + noteCheck(leftP, daNote); + } + + //this is already done in noteCheck / goodNoteHit + if (daNote.wasGoodHit) { - case 2: // NOTES YOU JUST PRESSED - if (upP || rightP || downP || leftP) - noteCheck(upP, daNote); - case 3: - if (upP || rightP || downP || leftP) - noteCheck(rightP, daNote); - case 1: - if (upP || rightP || downP || leftP) - noteCheck(downP, daNote); - case 0: - if (upP || rightP || downP || leftP) - noteCheck(leftP, daNote); + daNote.kill(); + notes.remove(daNote, true); + daNote.destroy(); } - - //this is already done in noteCheck / goodNoteHit - if (daNote.wasGoodHit) - { - daNote.kill(); - notes.remove(daNote, true); - daNote.destroy(); - } */ } else diff --git a/source/StoryMenuState.hx b/source/StoryMenuState.hx index 1e27eed7c..1c2dc8783 100644 --- a/source/StoryMenuState.hx +++ b/source/StoryMenuState.hx @@ -1,5 +1,8 @@ package; +#if desktop +import Discord.DiscordClient; +#end import flixel.FlxG; import flixel.FlxSprite; import flixel.addons.transition.FlxTransitionableState; @@ -109,6 +112,11 @@ class StoryMenuState extends MusicBeatState add(grpLocks); trace("Line 70"); + + #if desktop + // Updating Discord Rich Presence + DiscordClient.changePresence("In the Menus", null); + #end for (i in 0...weekData.length) { diff --git a/source/TitleState.hx b/source/TitleState.hx index 3a3041678..c91dc54eb 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -1,5 +1,9 @@ package; +#if desktop +import Discord.DiscordClient; +import sys.thread.Thread; +#end import flixel.FlxG; import flixel.FlxSprite; import flixel.FlxState; @@ -45,7 +49,7 @@ class TitleState extends MusicBeatState #if polymod polymod.Polymod.init({modRoot: "mods", dirs: ['introMod']}); #end - + PlayerSettings.init(); curWacky = FlxG.random.getObject(getIntroTextShit()); @@ -89,6 +93,10 @@ class TitleState extends MusicBeatState startIntro(); }); #end + + #if desktop + DiscordClient.initialize(); + #end } var logoBl:FlxSprite; @@ -282,12 +290,12 @@ class TitleState extends MusicBeatState if (version.trim() != NGio.GAME_VER_NUMS.trim() && !OutdatedSubState.leftState) { + FlxG.switchState(new OutdatedSubState()); trace('OLD VERSION!'); trace('old ver'); trace(version.trim()); trace('cur ver'); trace(NGio.GAME_VER_NUMS.trim()); - FlxG.switchState(new OutdatedSubState()); } else {