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
{