diff --git a/source/backend/ClientPrefs.hx b/source/backend/ClientPrefs.hx index 836d1f41..7adfe3c2 100644 --- a/source/backend/ClientPrefs.hx +++ b/source/backend/ClientPrefs.hx @@ -73,6 +73,7 @@ class SaveVariables { public var comboOffsetOP1:Array = [0, 0, 0, 0]; public var comboOffsetOP2:Array = [0, 0, 0, 0]; public var disableStrumMovement:Bool = false; + public var unlockFramerate:Bool = false; public function new() { @@ -197,7 +198,10 @@ class ClientPrefs { FlxG.autoPause = ClientPrefs.data.autoPause; #end - if(data.framerate > FlxG.drawFramerate) { + if (ClientPrefs.data.unlockFramerate) { + FlxG.updateFramerate = 999; + FlxG.drawFramerate = 999; + } else if(data.framerate > FlxG.drawFramerate) { FlxG.updateFramerate = data.framerate; FlxG.drawFramerate = data.framerate; } else { diff --git a/source/backend/Discord.hx b/source/backend/Discord.hx index 0956b9a7..40b2e28c 100644 --- a/source/backend/Discord.hx +++ b/source/backend/Discord.hx @@ -1,5 +1,9 @@ package backend; +import online.states.Room; +import online.Waiter; +import haxe.crypto.Md5; +import online.GameClient; import Sys.sleep; import discord_rpc.DiscordRpc; import lime.app.Application; @@ -10,7 +14,7 @@ class DiscordClient private static var _defaultID:String = "1185697129717583982"; public static var clientID(default, set):String = _defaultID; - private static var _options:Dynamic = { + private static var _options:DiscordPresenceOptions = { details: "In the Menus", state: null, largeImageKey: 'icon', @@ -27,7 +31,9 @@ class DiscordClient clientID: clientID, onReady: onReady, onError: onError, - onDisconnected: onDisconnected + onDisconnected: onDisconnected, + onRequest: onRequest, + onJoin: onJoin }); trace("Discord Client started."); @@ -42,6 +48,24 @@ class DiscordClient //DiscordRpc.shutdown(); } + static function onRequest(req:Dynamic) { + DiscordRpc.respond(req.userId, !GameClient.room.state.isPrivate ? Reply.Yes : Reply.No); + } + + static function onJoin(secret:String) { + Waiter.put(() -> { + GameClient.joinRoom(secret, (err) -> { + if (err != null) { + return; + } + + Waiter.put(() -> { + MusicBeatState.switchState(new Room()); + }); + }); + }); + } + public static function check() { if(!ClientPrefs.data.discordRPC) @@ -121,10 +145,36 @@ class DiscordClient // Obtained times are in milliseconds so they are divided so Discord can use it _options.startTimestamp = Std.int(startTimestamp / 1000); _options.endTimestamp = Std.int(endTimestamp / 1000); - DiscordRpc.presence(_options); + updateOnlinePresence(); + //DiscordRpc.presence(_options); //trace('Discord RPC Updated. Arguments: $details, $state, $smallImageKey, $hasStartTimestamp, $endTimestamp'); } + + public static function updateOnlinePresence() { + if (GameClient.isConnected()) { + if (!GameClient.room.state.isPrivate) { + _options.partyID = GameClient.rpcClientRoomID; + _options.joinSecret = GameClient.getRoomSecret(true); + _options.state = "In a Public Room"; + } + else { + _options.partyID = null; + _options.joinSecret = null; + _options.state = "In a Private Room"; + } + _options.partySize = GameClient.getPlayerCount(); + _options.partyMax = 2; + } + else { + _options.partyID = null; + _options.joinSecret = null; + _options.partySize = 0; + _options.partyMax = 0; + _options.state = null; + } + DiscordRpc.presence(_options); + } public static function resetClientID() clientID = _defaultID; diff --git a/source/backend/WeekData.hx b/source/backend/WeekData.hx index 9dde9273..ca5ac605 100644 --- a/source/backend/WeekData.hx +++ b/source/backend/WeekData.hx @@ -82,8 +82,11 @@ class WeekData { this.fileName = fileName; } - public static function reloadWeekFiles(isStoryMode:Null = false) + public static function reloadWeekFiles(?isStoryMode:Null /*= false*/) { + if (isStoryMode == null) // dead code btw + isStoryMode = PlayState.isStoryMode; + weeksList = []; weeksLoaded.clear(); #if MODS_ALLOWED @@ -112,7 +115,12 @@ class WeekData { } #end - if(weekFile != null && (isStoryMode == null || (isStoryMode && !weekFile.hideStoryMode) || (!isStoryMode && !weekFile.hideFreeplay))) { + if ( + weekFile != null && ( + (online.GameClient.isConnected() && !isStoryMode) || //freeplay unlocked patched ad free + ((isStoryMode && !weekFile.hideStoryMode) || (!isStoryMode && !weekFile.hideFreeplay)) + ) + ) { weeksLoaded.set(sexList[i], weekFile); weeksList.push(sexList[i]); } @@ -131,7 +139,7 @@ class WeekData { var path:String = directory + daWeek + '.json'; if(sys.FileSystem.exists(path)) { - addWeek(daWeek, path, directories[i], i, originalLength); + addWeek(isStoryMode, daWeek, path, directories[i], i, originalLength); } } @@ -140,7 +148,7 @@ class WeekData { var path = haxe.io.Path.join([directory, file]); if (!sys.FileSystem.isDirectory(path) && file.endsWith('.json')) { - addWeek(file.substr(0, file.length - 5), path, directories[i], i, originalLength); + addWeek(isStoryMode, file.substr(0, file.length - 5), path, directories[i], i, originalLength); } } } @@ -148,7 +156,7 @@ class WeekData { #end } - private static function addWeek(weekToCheck:String, path:String, directory:String, i:Int, originalLength:Int) + private static function addWeek(isStoryMode:Bool, weekToCheck:String, path:String, directory:String, i:Int, originalLength:Int) { if(!weeksLoaded.exists(weekToCheck)) { @@ -162,7 +170,9 @@ class WeekData { weekFile.folder = directory.substring(Paths.mods().length, directory.length-1); #end } - if((PlayState.isStoryMode && !weekFile.hideStoryMode) || (!PlayState.isStoryMode && !weekFile.hideFreeplay)) + if( + (online.GameClient.isConnected() && !isStoryMode) || // freeplay unlocked patched ad free + ((isStoryMode && !weekFile.hideStoryMode) || (!isStoryMode && !weekFile.hideFreeplay))) { weeksLoaded.set(weekToCheck, weekFile); weeksList.push(weekToCheck); diff --git a/source/online/FunkinPoints.hx b/source/online/FunkinPoints.hx index 0179717b..01e950ce 100644 --- a/source/online/FunkinPoints.hx +++ b/source/online/FunkinPoints.hx @@ -5,7 +5,7 @@ import online.states.ResultsScreen; @:build(online.Macros.getSetForwarder()) class FunkinPoints { @:forwardField(FlxG.save.data.funkinPointsv1, 0) - public static var funkinPoints(get, null):Float; + public static var funkinPoints(get, set):Float; public static function calcFP(accuracy:Float, misses:Float, noteDensity:Float, notesHit:Float, combo:Float, songSpeed:Float):Float { if (accuracy <= 0) diff --git a/source/online/GameClient.hx b/source/online/GameClient.hx index 6d622e1c..32a3dbae 100644 --- a/source/online/GameClient.hx +++ b/source/online/GameClient.hx @@ -1,5 +1,6 @@ package online; +import haxe.crypto.Md5; import backend.Song; import backend.Rating; import online.schema.Player; @@ -22,6 +23,7 @@ class GameClient { public static var isOwner:Bool; public static var address:String; public static var reconnectTries:Int = 0; + public static var rpcClientRoomID:String; /** * the server address that the player set, if player set nothing then it returns `serverAddresses[0]` @@ -41,6 +43,9 @@ class GameClient { client = new Client(address); client.create("room", getOptions(true), RoomState, (err, room) -> _onJoin(err, room, true, address, onJoin)); + }, (exc) -> { + LoadingScreen.toggle(false); + Alert.alert("Failed to connect!", exc.toString()); }); } @@ -61,6 +66,9 @@ class GameClient { client = new Client(roomAddress); client.joinById(roomID, getOptions(false), RoomState, (err, room) -> _onJoin(err, room, false, roomAddress, onJoin)); + }, (exc) -> { + LoadingScreen.toggle(false); + Alert.alert("Failed to connect!", exc.toString()); }); } @@ -77,6 +85,7 @@ class GameClient { GameClient.room = room; GameClient.isOwner = isHost; GameClient.address = address; + GameClient.rpcClientRoomID = Md5.encode(FlxG.random.int(0, 1000000).hex()); clearOnMessage(); GameClient.room.onError += (id:Int, e:String) -> { @@ -178,6 +187,7 @@ class GameClient { GameClient.room = null; GameClient.isOwner = false; GameClient.address = null; + GameClient.rpcClientRoomID = null; //Downloader.cancelAll(); }); @@ -219,6 +229,12 @@ class GameClient { #end }); }); + + #if desktop + GameClient.room.state.listen("isPrivate", (value, prev) -> { + DiscordClient.updateOnlinePresence(); + }); + #end } public static function send(type:Dynamic, ?message:Null) { @@ -268,7 +284,7 @@ class GameClient { }); } - public static function getPlayerCount(callback:(v:Null)->Void) { + public static function getServerPlayerCount(callback:(v:Null)->Void) { Thread.run(() -> { var http = new Http(addressToUrl(serverAddress) + "/api/online"); @@ -328,4 +344,13 @@ class GameClient { GameClient.send("setGameplaySetting", [key, value]); } } + + public static function getPlayerCount():Int { + if (!GameClient.isConnected()) + return 0; + + if (GameClient.room.state.player2 != null && GameClient.room.state.player2.name != "") + return 2; + return 1; + } } \ No newline at end of file diff --git a/source/online/Macros.hx b/source/online/Macros.hx index 9547d9bf..1ee9f90a 100644 --- a/source/online/Macros.hx +++ b/source/online/Macros.hx @@ -25,7 +25,12 @@ class Macros { access: fieldAccess, kind: FieldType.FFun({ args: [], - expr: macro return ${meta.params[0]} ?? ${meta.params[1]} + expr: macro { + if (${meta.params[0]} == null) + ${meta.params[0]} = ${meta.params[1]}; + + return ${meta.params[0]} + } }), pos: pos, }); diff --git a/source/online/Thread.hx b/source/online/Thread.hx index ce08a761..91f21397 100644 --- a/source/online/Thread.hx +++ b/source/online/Thread.hx @@ -1,14 +1,19 @@ package online; +import haxe.Exception; + class Thread { - public static function run(func:Void->Void) { + public static function run(func:Void->Void, ?onException:Exception->Void) { sys.thread.Thread.create(() -> { try { func(); } catch (exc) { Waiter.put(() -> { // waiter more errors please! - throw exc; + if (onException != null) + onException(exc); + else + throw exc; }); } }); diff --git a/source/online/states/BananaDownload.hx b/source/online/states/BananaDownload.hx index 1da9766e..8c5ceaa9 100644 --- a/source/online/states/BananaDownload.hx +++ b/source/online/states/BananaDownload.hx @@ -29,6 +29,8 @@ class BananaDownload extends MusicBeatState { DiscordClient.changePresence("Browsing mods on GameBanana.", null, null, false); #end + GameClient.send("status", "Browsing mods on GameBanana"); + var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat')); bg.color = 0xff46463b; bg.updateHitbox(); @@ -143,7 +145,7 @@ class BananaDownload extends MusicBeatState { if (!searchInput.hasFocus) { if (controls.BACK) { FlxG.sound.music.volume = 1; - MusicBeatState.switchState(new OnlineState()); + MusicBeatState.switchState(GameClient.isConnected() ? new Room() : new OnlineState()); FlxG.sound.play(Paths.sound('cancelMenu')); } diff --git a/source/online/states/OnlineState.hx b/source/online/states/OnlineState.hx index 8a412b64..53ba1d53 100644 --- a/source/online/states/OnlineState.hx +++ b/source/online/states/OnlineState.hx @@ -77,7 +77,7 @@ class OnlineState extends MusicBeatState { OnlineMods.checkMods(); #if desktop - DiscordClient.changePresence("In online lobby.", null, null, false); + DiscordClient.changePresence("In the Online Menu.", null, null, false); #end var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat')); @@ -136,7 +136,7 @@ class OnlineState extends MusicBeatState { changeSelection(0); - GameClient.getPlayerCount((v) -> { + GameClient.getServerPlayerCount((v) -> { if (v == null) { playersOnline.text = "OFFLINE"; //thought this would look cool diff --git a/source/online/states/Room.hx b/source/online/states/Room.hx index d526f3a7..db8568cf 100644 --- a/source/online/states/Room.hx +++ b/source/online/states/Room.hx @@ -69,17 +69,6 @@ class Room extends MusicBeatState { }); }); - GameClient.room.state.listen("isPrivate", (value, prev) -> { - #if desktop - if (value) { - DiscordClient.changePresence("In a online room.", "Private room.", null, false); - } - else { - DiscordClient.changePresence("In a online room.", "Public room: " + GameClient.getRoomSecret(), null, false); - } - #end - }); - playMusic((GameClient.isOwner ? GameClient.room.state.player1 : GameClient.room.state.player2).hasSong); (GameClient.isOwner ? GameClient.room.state.player1 : GameClient.room.state.player2).listen("hasSong", (value:Bool, prev) -> { Waiter.put(() -> { @@ -152,6 +141,10 @@ class Room extends MusicBeatState { override function create() { super.create(); + #if desktop + DiscordClient.changePresence("In the Lobby", null, null, false); + #end + WeekData.reloadWeekFiles(false); for (i in 0...WeekData.weeksList.length) { WeekData.setDirectoryFromWeek(WeekData.weeksLoaded.get(WeekData.weeksList[i])); @@ -498,12 +491,7 @@ class Room extends MusicBeatState { if (elapsedShit >= 3) { elapsedShit = 0; - if (GameClient.room.state.isPrivate) { - DiscordClient.changePresence("In a online room.", "Private room.", null, false); - } - else { - DiscordClient.changePresence("In a online room.", "Public room: " + GameClient.getRoomSecret(), null, false); - } + DiscordClient.updateOnlinePresence(); } #end @@ -639,7 +627,10 @@ class Room extends MusicBeatState { optionShake = FlxTween.shake(songName, 0.05, 0.3, FlxAxes.X); } case 5: - verifyDownloadMod(); + if (verifyDownloadMod()) { + GameClient.clearOnMessage(); + MusicBeatState.switchState(new BananaDownload()); + } } } @@ -665,25 +656,33 @@ class Room extends MusicBeatState { try { if (GameClient.room.state.song == "") { if (ignoreAlert) - return; + return false; + + if (GameClient.hasPerms()) + return true; + Alert.alert("Song isn't selected!"); var sond = FlxG.sound.play(Paths.sound('badnoise' + FlxG.random.int(1, 3))); sond.pitch = 1.1; if (optionShake != null) optionShake.cancel(); optionShake = FlxTween.shake(verifyMod, 0.05, 0.3, FlxAxes.X); - return; + return false; } if (getSelfPlayer().hasSong) { if (ignoreAlert) - return; + return false; + + if (GameClient.hasPerms()) + return true; + Alert.alert("You already have this song installed!"); var sond = FlxG.sound.play(Paths.sound('badnoise' + FlxG.random.int(1, 3))); sond.pitch = 1.1; if (optionShake != null) optionShake.cancel(); optionShake = FlxTween.shake(verifyMod, 0.05, 0.3, FlxAxes.X); - return; + return false; } if (Mods.getModDirectories().contains(GameClient.room.state.modDir) || GameClient.room.state.modDir == "") { @@ -693,7 +692,7 @@ class Room extends MusicBeatState { } catch (exc) { } - return; + return false; } if (GameClient.room.state.modDir != null && GameClient.room.state.modURL != null && GameClient.room.state.modURL != "") { @@ -721,12 +720,13 @@ class Room extends MusicBeatState { if (optionShake != null) optionShake.cancel(); optionShake = FlxTween.shake(verifyMod, 0.05, 0.3, FlxAxes.X); - return; } } catch (exc) { Sys.println(exc); } + + return false; } function updateTexts() { diff --git a/source/openfl/display/FPS.hx b/source/openfl/display/FPS.hx index 1d910af7..a8161992 100644 --- a/source/openfl/display/FPS.hx +++ b/source/openfl/display/FPS.hx @@ -81,7 +81,8 @@ class FPS extends TextField var currentCount = times.length; currentFPS = Math.round((currentCount + cacheCount) / 2); - if (currentFPS > ClientPrefs.data.framerate) currentFPS = ClientPrefs.data.framerate; + var optionFramerate = ClientPrefs.data.unlockFramerate ? 999 : ClientPrefs.data.framerate; + if (currentFPS > optionFramerate) currentFPS = optionFramerate; if (currentCount != cacheCount /*&& visible*/) { @@ -106,7 +107,7 @@ class FPS extends TextField #end textColor = 0xFFFFFFFF; - if (memoryMegas > 3000 || currentFPS <= ClientPrefs.data.framerate / 2) + if (memoryMegas > 3000 || currentFPS <= optionFramerate / 2) { textColor = 0xFFFF0000; } diff --git a/source/options/GraphicsSettingsSubState.hx b/source/options/GraphicsSettingsSubState.hx index 996c4c4d..f7e325da 100644 --- a/source/options/GraphicsSettingsSubState.hx +++ b/source/options/GraphicsSettingsSubState.hx @@ -46,6 +46,14 @@ class GraphicsSettingsSubState extends BaseOptionsMenu addOption(option); #if !html5 //Apparently other framerates isn't correctly supported on Browser? Probably it has some V-Sync shit enabled by default, idk + + var option:Option = new Option('Unlock FPS', //Name + "If checked, the FPS timer will be set to 999 (this can't be infinite for obvious reasons)", //Description + 'unlockFramerate', + 'bool'); + option.onChange = onChangeFramerate; + addOption(option); + var option:Option = new Option('Framerate', "Pretty self explanatory, isn't it?", 'framerate', @@ -75,6 +83,13 @@ class GraphicsSettingsSubState extends BaseOptionsMenu function onChangeFramerate() { + if (ClientPrefs.data.unlockFramerate) { + FlxG.updateFramerate = 999; + FlxG.drawFramerate = 999; + return; + } + + if(ClientPrefs.data.framerate > FlxG.drawFramerate) { FlxG.updateFramerate = ClientPrefs.data.framerate; diff --git a/source/psychlua/FunkinLua.hx b/source/psychlua/FunkinLua.hx index 4948e632..7ebb730a 100644 --- a/source/psychlua/FunkinLua.hx +++ b/source/psychlua/FunkinLua.hx @@ -171,7 +171,7 @@ class FunkinLua { // Some settings, no jokes set('downscroll', ClientPrefs.data.downScroll); set('middlescroll', ClientPrefs.data.middleScroll); - set('framerate', ClientPrefs.data.framerate); + set('framerate', ClientPrefs.data.unlockFramerate ? 999 : ClientPrefs.data.framerate); set('ghostTapping', ClientPrefs.data.ghostTapping); set('hideHud', ClientPrefs.data.hideHud); set('timeBarType', ClientPrefs.data.timeBarType);