From 9a38232fd45fa68c225969b7549b8c72a6851cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sat, 23 Mar 2024 01:29:48 +0100 Subject: [PATCH 01/21] hxdiscord_rpc, away3D fork and much more 5H FOR COMPILING. 5 FUCKING HOURS FOR MACRO ERRORS. Co-Authored-By: Ne_Eo --- README.md | 3 +- assets/shaders/engine/editorWaveforms.frag | 71 +++-- libs.xml | 4 +- project.xml | 3 +- .../events/DiscordPresenceUpdateEvent.hx | 6 +- source/funkin/backend/system/github/GitHub.hx | 64 +--- source/funkin/backend/system/macros/Utils.hx | 17 ++ source/funkin/backend/utils/DiscordUtil.hx | 282 ++++++++++++++---- source/funkin/backend/utils/HttpUtil.hx | 71 +++++ source/funkin/game/NoteGroup.hx | 1 + .../funkin/options/type/GithubIconOption.hx | 4 +- 11 files changed, 355 insertions(+), 171 deletions(-) create mode 100644 source/funkin/backend/utils/HttpUtil.hx diff --git a/README.md b/README.md index d09c559a..ac87a79c 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,5 @@ In the future (when the engine won't be a WIP anymore) we're gonna also publish - Credits to [Ne_Eo](https://twitter.com/Ne_Eo_Twitch) and the [3D-HaxeFlixel](https://github.com/lunarcleint/3D-HaxeFlixel) repository for Away3D Flixel support - Credits to the [FlxAnimate](https://github.com/Dot-Stuff/flxanimate) team for the Animate Atlas support - Credits to Smokey555 for the backup Animate Atlas to spritesheet code -- Credits to MAJigsaw77 for [hxvlc](https://github.com/MAJigsaw77/hxvlc) for video cutscene/mp4 support -- Credits to Aidan63 for [discord-rpc](https://github.com/Aidan63/linc_discord-rpc) for discord rpc integration +- Credits to MAJigsaw77 for [hxvlc](https://github.com/MAJigsaw77/hxvlc) (video cutscene/mp4 support) and [hxdiscord_rpc](https://github.com/MAJigsaw77/hxdiscord_rpc) (discord rpc integration) diff --git a/assets/shaders/engine/editorWaveforms.frag b/assets/shaders/engine/editorWaveforms.frag index 7a424adb..53fc9fdf 100644 --- a/assets/shaders/engine/editorWaveforms.frag +++ b/assets/shaders/engine/editorWaveforms.frag @@ -2,11 +2,11 @@ // Used in charter by waveforms -const vec3 gradient1 = vec3(114./255., 81./255., 135./255); -const vec3 gradient2 = vec3(144./255., 80./255., 186./255); +const vec3 gradient1 = vec3(114.0/255.0, 81.0/255.0, 135.0/255.0); +const vec3 gradient2 = vec3(144.0/255.0, 80.0/255.0, 186.0/255.0); -const vec4 outlinecolor = vec4(vec3(.1), .1); -const vec3 lowdetailcol = vec3(0., 0., 1.); +const vec4 outlinecolor = vec4(0.1); +const vec3 lowdetailcol = vec3(0.0, 0.0, 1.0); uniform vec2 textureRes; uniform float pixelOffset; @@ -19,18 +19,17 @@ uniform ivec2 waveformSize; uniform bool lowDetail; float getAmplitude(vec2 pixel) { - float pixelID = floor((pixel.y+pixelOffset)/3.); - + float pixelID = floor((pixel.y+pixelOffset)/3.0); + // TODO: INVESTIGATE THE 1.+ AND WHY IT WORKS (SRSLY I GOT NO CLUE) -lunar - vec2 wavePixel = vec2(mod(pixelID,waveformSize.x), 1.+floor(pixelID/waveformSize.x)); + vec2 wavePixel = vec2(mod(pixelID,waveformSize.x), 1.0+floor(pixelID/waveformSize.x)); vec4 waveData = texture2D(waveformTexture, wavePixel / waveformSize); - switch (int(mod(wavePixel.x, 3.))) { - case 0: return waveData.r; break; - case 1: return waveData.g; break; - case 2: return waveData.b; break; - } - return 0.; + int id = int(mod(wavePixel.x, 3.0)); + if(id == 0) return waveData.r; + if(id == 1) return waveData.g; + if(id == 2) return waveData.b; + return 0.0; } bool inWaveForm(vec2 pixel, float width) { @@ -41,40 +40,40 @@ bool inWaveForm(vec2 pixel, float width) { void highDetailWaveform(vec2 pixel, float amplitude, float ampwidth) { if (inWaveForm(pixel, ampwidth)) { vec3 gradientColor = mix(gradient1, gradient2, openfl_TextureCoordv.x); - gradientColor *= pixel.y+pixelOffset>playerPosition ? .7 : 1.; + gradientColor *= pixel.y+pixelOffset>playerPosition ? 0.7 : 1.0; - float remapCoord = (amplitude/textureRes.x)/2.; + float remapCoord = (amplitude/textureRes.x)/2.0; - float mappedCoord = map(openfl_TextureCoordv.x, remapCoord, 1.-remapCoord, 0., 1.); - float hightlightAmount = 1.-(abs(mappedCoord-0.5)*2.); + float mappedCoord = map(openfl_TextureCoordv.x, remapCoord, 1.0-remapCoord, 0.0, 1.0); + float hightlightAmount = 1.0-(abs(mappedCoord-0.5)*2.0); - gradientColor = mix(gradientColor, gradientColor * vec3(1.8), map(hightlightAmount, 0., 1., .5, 1.)); + gradientColor = mix(gradientColor, gradientColor * vec3(1.8), map(hightlightAmount, 0.0, 1.0, 0.5, 1.0)); - float ampwidthHighlight = (1.-(amplitude*(1./3.))) * textureRes.x; + float ampwidthHighlight = (1.0-(amplitude*(1.0/3.0))) * textureRes.x; if (inWaveForm(pixel, ampwidthHighlight)) { - float remapCoord = (ampwidthHighlight/textureRes.x)/2.; + float remapCoord = (ampwidthHighlight/textureRes.x)/2.0; - float mappedCoord = map(openfl_TextureCoordv.x, remapCoord, 1.-remapCoord, 0., 1.); - float hightlightAmount = 1.-(abs(mappedCoord-0.5)*2.); + float mappedCoord = map(openfl_TextureCoordv.x, remapCoord, 1.0-remapCoord, 0.0, 1.0); + float hightlightAmount = 1.0-(abs(mappedCoord-0.5)*2.0); - gradientColor = mix(gradientColor, gradientColor * vec3(1.8), map(hightlightAmount, 0., 1., .5, 1.)); + gradientColor = mix(gradientColor, gradientColor * vec3(1.8), map(hightlightAmount, 0.0, 1.0, 0.5, 1.0)); } - - gl_FragColor = vec4(vec3(gradientColor * mix(0.5, .8, amplitude))*openfl_Alphav, openfl_Alphav); - float lastAmplitude = getAmplitude(pixel - vec2(0., -1.)); - float lastAmpwidth = (1.-lastAmplitude) * textureRes.x; + gl_FragColor = vec4(vec3(gradientColor * mix(0.5, 0.8, amplitude))*openfl_Alphav, openfl_Alphav); + + float lastAmplitude = getAmplitude(pixel - vec2(0.0, -1.0)); + float lastAmpwidth = (1.0-lastAmplitude) * textureRes.x; if (!inWaveForm(pixel, lastAmpwidth)) - gl_FragColor -= outlinecolor*mix(0.5, .8, amplitude); + gl_FragColor -= outlinecolor*mix(0.5, 0.8, amplitude); - float nextAmplitude = getAmplitude(pixel - vec2(0., 1.)); - float nextAmpwidth = (1.-nextAmplitude) * textureRes.x; + float nextAmplitude = getAmplitude(pixel - vec2(0.0, 1.0)); + float nextAmpwidth = (1.0-nextAmplitude) * textureRes.x; if (!inWaveForm(pixel, nextAmpwidth)) - gl_FragColor -= outlinecolor*mix(0.5, .8, amplitude); + gl_FragColor -= outlinecolor*mix(0.5, 0.8, amplitude); - if (!inWaveForm(pixel, ampwidth+2.) && amplitude > 0.) + if (!inWaveForm(pixel, ampwidth+2.0) && amplitude > 0.0) gl_FragColor -= outlinecolor; } } @@ -82,9 +81,9 @@ void highDetailWaveform(vec2 pixel, float amplitude, float ampwidth) { void lowDetailWaveform(vec2 pixel, float amplitude, float ampwidth) { if (inWaveForm(pixel, ampwidth)) { vec3 color = lowdetailcol; - color *= pixel.y+pixelOffset>playerPosition ? .7 : 1.; + color *= pixel.y+pixelOffset>playerPosition ? 0.7 : 1.0; - gl_FragColor = vec4(color, 1.); + gl_FragColor = vec4(color, 1.0); } } @@ -93,10 +92,10 @@ void main() vec2 pixel = openfl_TextureCoordv * textureRes; float amplitude = getAmplitude(pixel); - float ampwidth = (1.-amplitude) * textureRes.x; + float ampwidth = (1.0-amplitude) * textureRes.x; if (lowDetail) lowDetailWaveform(pixel, amplitude, ampwidth); - else + else highDetailWaveform(pixel, amplitude, ampwidth); } \ No newline at end of file diff --git a/libs.xml b/libs.xml index 81618ce1..5afacfc3 100644 --- a/libs.xml +++ b/libs.xml @@ -10,12 +10,12 @@ - + - + diff --git a/project.xml b/project.xml index aee55825..6f26ce30 100644 --- a/project.xml +++ b/project.xml @@ -170,10 +170,11 @@ - + + diff --git a/source/funkin/backend/scripting/events/DiscordPresenceUpdateEvent.hx b/source/funkin/backend/scripting/events/DiscordPresenceUpdateEvent.hx index 782d70a0..c17cbb68 100644 --- a/source/funkin/backend/scripting/events/DiscordPresenceUpdateEvent.hx +++ b/source/funkin/backend/scripting/events/DiscordPresenceUpdateEvent.hx @@ -1,12 +1,8 @@ package funkin.backend.scripting.events; -#if DISCORD_RPC -import discord_rpc.DiscordRpc.DiscordPresenceOptions; -#end - final class DiscordPresenceUpdateEvent extends CancellableEvent { /** * Object containing all of the data for the presence. Can be altered. */ - public var presenceData:#if DISCORD_RPC DiscordPresenceOptions #else Dynamic #end; + public var presence:funkin.backend.utils.DiscordUtil.DPresence; } \ No newline at end of file diff --git a/source/funkin/backend/system/github/GitHub.hx b/source/funkin/backend/system/github/GitHub.hx index fa664112..27ba825b 100644 --- a/source/funkin/backend/system/github/GitHub.hx +++ b/source/funkin/backend/system/github/GitHub.hx @@ -3,7 +3,6 @@ package funkin.backend.system.github; #if GITHUB_API import haxe.Json; import haxe.Exception; -import haxe.Http; #end // TODO: Document further and perhaps make this a Haxelib. @@ -18,7 +17,7 @@ class GitHub { public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array { #if GITHUB_API try { - var data = Json.parse(__requestOnGitHubServers('https://api.github.com/repos/${user}/${repository}/releases')); + var data = Json.parse(HttpUtil.requestText('https://api.github.com/repos/${user}/${repository}/releases')); if (!(data is Array)) throw __parseGitHubException(data); @@ -41,7 +40,7 @@ class GitHub { public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array { #if GITHUB_API try { - var data = Json.parse(__requestOnGitHubServers('https://api.github.com/repos/${user}/${repository}/contributors')); + var data = Json.parse(HttpUtil.requestText('https://api.github.com/repos/${user}/${repository}/contributors')); if (!(data is Array)) throw __parseGitHubException(data); @@ -63,7 +62,7 @@ class GitHub { public static function getOrganization(org:String, ?onError:Exception->Void):GitHubOrganization { #if GITHUB_API try { - var data = Json.parse(__requestOnGitHubServers('https://api.github.com/orgs/$org')); + var data = Json.parse(HttpUtil.requestText('https://api.github.com/orgs/$org')); if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data); @@ -86,7 +85,7 @@ class GitHub { public static function getOrganizationMembers(org:String, ?onError:Exception->Void):Array { #if GITHUB_API try { - var data = Json.parse(__requestOnGitHubServers('https://api.github.com/orgs/$org/members')); + var data = Json.parse(HttpUtil.requestText('https://api.github.com/orgs/$org/members')); if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data); @@ -111,7 +110,7 @@ class GitHub { try { var url = 'https://api.github.com/users/$user'; - var data = Json.parse(__requestOnGitHubServers(url)); + var data = Json.parse(HttpUtil.requestText(url)); if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data); @@ -134,59 +133,6 @@ class GitHub { public static inline function filterReleases(releases:Array, keepPrereleases:Bool = true, keepDrafts:Bool = false) return #if GITHUB_API [for(release in releases) if (release != null && (!release.prerelease || (release.prerelease && keepPrereleases)) && (!release.draft || (release.draft && keepDrafts))) release] #else releases #end; - public static function __requestOnGitHubServers(url:String) { - var r = null; - #if GITHUB_API - var h = new Http(url); - h.setHeader("User-Agent", "request"); - - h.onStatus = function(s) { - if(isRedirect(s)) - r = __requestOnGitHubServers(h.responseHeaders.get("Location")); - }; - - h.onData = function(d) { - if(r == null) r = d; - } - h.onError = function(e) { - throw e; - } - - h.request(false); - #end - return r; - } - public static function __requestBytesOnGitHubServers(url:String) { - var r = null; - #if GITHUB_API - var h = new Http(url); - h.setHeader("User-Agent", "request"); - - h.onStatus = function(s) { - if(isRedirect(s)) - r = __requestBytesOnGitHubServers(h.responseHeaders.get("Location")); - }; - - h.onBytes = function(d) { - if(r == null) r = d; - } - h.onError = function(e) { - throw e; - } - - h.request(false); - #end - return r; - } - private static function isRedirect(status:Int):Bool { - switch (status) { - // 301: Moved Permanently, 302: Found (Moved Temporarily), 307: Temporary Redirect, 308: Permanent Redirect - Nex - case 301 | 302 | 307 | 308 : - trace("Redirected with status code: " + status); - return true; - } - return false; - } private static function __parseGitHubException(obj:Dynamic):GitHubException { #if GITHUB_API var msg:String = "(No message)"; diff --git a/source/funkin/backend/system/macros/Utils.hx b/source/funkin/backend/system/macros/Utils.hx index df25030c..1d4873f4 100644 --- a/source/funkin/backend/system/macros/Utils.hx +++ b/source/funkin/backend/system/macros/Utils.hx @@ -37,4 +37,21 @@ class Utils { return expr; #end } + + public static macro function safeSet(variable:Null, value:Null):Null { + #if macro + return macro if (${value} != null) ${variable} = ${value}; + #end + } + public static macro function safeSetWrapper(variable:Null, value:Null, wrapper:Null):Null { + #if macro + return macro if (${value} != null) ${variable} = ${wrapper}(${value}); + #end + } + + public static macro function safeReflection(variable:Null, value:Null, field:Null):Null { + #if macro + return macro if (Reflect.hasField(${value}, ${field})) ${variable} = Reflect.field(${value}, ${field}); + #end + } } \ No newline at end of file diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index cdd24b6c..733790fa 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -1,62 +1,77 @@ package funkin.backend.utils; +import flixel.util.typeLimit.OneOfTwo; +import openfl.display.BitmapData; +import funkin.backend.system.macros.Utils; import funkin.backend.scripting.events.DiscordPresenceUpdateEvent; import haxe.Json; import flixel.sound.FlxSound; #if DISCORD_RPC -import discord_rpc.DiscordRpc; +import hxdiscord_rpc.Discord; +import hxdiscord_rpc.Types; import sys.thread.Thread; import Sys; import lime.app.Application; #end -class DiscordUtil { - public static var currentID:String = null; +class DiscordUtil +{ + public static var currentID(default, set):String = null; public static var discordThread:#if DISCORD_RPC Thread #else Dynamic #end = null; public static var ready:Bool = false; - public static var data:DiscordJson = null; - public static function init() { + public static var user:#if DISCORD_RPC DUser #else Dynamic #end = null; + public static var lastPresence:#if DISCORD_RPC DPresence #else Dynamic #end = null; + public static var config:#if DISCORD_RPC DiscordJson #else Dynamic #end = null; + + public static function init() + { #if DISCORD_RPC reloadJsonData(); - discordThread = Thread.create(function() { + + discordThread = Thread.create(function() + { while (true) { - while(!ready) { - Sys.sleep(1/60); + while (ready) + { + #if DISCORD_DISABLE_IO_THREAD + Discord.UpdateConnection(); + #end + Discord.RunCallbacks(); + + Sys.sleep(2); } - trace("Processing Discord RPC..."); - DiscordRpc.process(); - Sys.sleep(2); + + Sys.sleep(1); // to reduce cpu } }); - Application.current.onExit.add(function(exitCode) { - shutdown(); - }); + Application.current.onExit.add(function(_) shutdown()); #end } - public static function reloadJsonData() { + public static function reloadJsonData() + { #if DISCORD_RPC - data = {}; var jsonPath = Paths.json("config/discord"); - if (Assets.exists(jsonPath)) { - try { - data = Json.parse(Assets.getText(jsonPath)); - } catch(e) { + if (Assets.exists(jsonPath)) + { + try + config = Json.parse(Assets.getText(jsonPath)) + catch (e) Logs.trace('Couldn\'t load Discord RPC configuration: ${e.toString()}', ERROR); - } } - data.setFieldDefault("clientID", "1027994136193810442"); - data.setFieldDefault("logoKey", "icon"); - data.setFieldDefault("logoText", Application.current.meta.get('title')); - changeClientID(data.clientID); + config.logoKey = config.logoKey.getDefault("icon"); + config.logoText = config.logoText.getDefault(Application.current.meta.get('title')); + config.clientID = config.clientID.getDefault("1027994136193810442"); + currentID = config.clientID; #end } - public static function changePresence(details:String, state:String, ?smallImageKey : String) { + public static function changePresence(details:String, state:String, ?smallImageKey:String) + { #if DISCORD_RPC changePresenceAdvanced({ state: state, @@ -66,12 +81,14 @@ class DiscordUtil { #end } - public static function changeSongPresence(details:String, state:String, audio:FlxSound, ?smallImageKey : String) { + public static function changeSongPresence(details:String, state:String, audio:FlxSound, ?smallImageKey:String) + { #if DISCORD_RPC var start:Float = 0; var end:Float = 0; - if (audio != null && audio.playing) { + if (audio != null && audio.playing) + { start = Date.now().getTime(); end = start + (audio.length - audio.time); } @@ -86,66 +103,203 @@ class DiscordUtil { #end } - public static function changePresenceAdvanced(data:#if DISCORD_RPC DiscordPresenceOptions #else Dynamic #end) { - #if DISCORD_RPC - if (data == null) return; + @:noCompletion public static function fixString(str:String) + { + return new cpp.ConstCharStar(cast(str, String)); + } + @:noCompletion public static function toString(str:cpp.ConstCharStar) + { + return cast(str, String); + } + + public static function changePresenceAdvanced(data:DPresence) + { + #if DISCORD_RPC + if (data == null) + return; + + // copy last presence if (data.largeImageKey == null) - data.largeImageKey = DiscordUtil.data.logoKey; + data.largeImageKey = config.logoKey; if (data.largeImageText == null) - data.largeImageText = DiscordUtil.data.logoText; + data.largeImageText = config.logoText; #if GLOBAL_SCRIPT var event = funkin.backend.scripting.GlobalScript.event("onDiscordPresenceUpdate", EventManager.get(DiscordPresenceUpdateEvent).recycle(data)); - if (event.cancelled) return; + if (event.cancelled) + return; + data = event.presence; #end + lastPresence = data; - DiscordRpc.presence(data); + var dp:DiscordRichPresence = DiscordRichPresence.create(); + // TODO: make this use a reflection-like macro + // strings + /*if(data.state != null) dp.state = fixString(data.state); + if(data.details != null) dp.details = fixString(data.details); + if(data.largeImageKey != null) dp.largeImageKey = fixString(data.largeImageKey); + if(data.largeImageText != null) dp.largeImageText = fixString(data.largeImageText); + if(data.smallImageKey != null) dp.smallImageKey = fixString(data.smallImageKey); + if(data.smallImageText != null) dp.smallImageText = fixString(data.smallImageText); + if(data.partyId != null) dp.partyId = fixString(data.partyId); + if(data.matchSecret != null) dp.matchSecret = fixString(data.matchSecret); + if(data.joinSecret != null) dp.joinSecret = fixString(data.joinSecret); + if(data.spectateSecret != null) dp.spectateSecret = fixString(data.spectateSecret); + + // other + if(data.startTimestamp != null) dp.startTimestamp = data.startTimestamp; + if(data.endTimestamp != null) dp.endTimestamp = data.endTimestamp; + if(data.partySize != null) dp.partySize = data.partySize; + if(data.partyMax != null) dp.partyMax = data.partyMax; + if(data.partyPrivacy != null) dp.partyPrivacy = data.partyPrivacy; + if(data.instance != null) dp.instance = data.instance; */ + + Utils.safeSetWrapper(dp.state, data.state, fixString); + Utils.safeSetWrapper(dp.details, data.details, fixString); + Utils.safeSet(dp.startTimestamp, data.startTimestamp); + Utils.safeSet(dp.endTimestamp, data.endTimestamp); + Utils.safeSetWrapper(dp.largeImageKey, data.largeImageKey, fixString); + Utils.safeSetWrapper(dp.largeImageText, data.largeImageText, fixString); + Utils.safeSetWrapper(dp.smallImageKey, data.smallImageKey, fixString); + Utils.safeSetWrapper(dp.smallImageText, data.smallImageText, fixString); + Utils.safeSetWrapper(dp.partyId, data.partyId, fixString); + Utils.safeSet(dp.partySize, data.partySize); + Utils.safeSet(dp.partyMax, data.partyMax); + Utils.safeSet(dp.partyPrivacy, data.partyPrivacy); + Utils.safeSetWrapper(dp.matchSecret, data.matchSecret, fixString); + Utils.safeSetWrapper(dp.joinSecret, data.joinSecret, fixString); + Utils.safeSetWrapper(dp.spectateSecret, data.spectateSecret, fixString); + Utils.safeSet(dp.instance, data.instance); + + Discord.UpdatePresence(cpp.RawConstPointer.addressOf(dp)); #end } - public static function changeClientID(id:String) { - #if DISCORD_RPC - if (currentID != null) { - DiscordRpc.shutdown(); - } + private static function set_currentID(id:String):String + { + if (currentID == id) + return id; + #if DISCORD_RPC + if (currentID != null) + shutdown(); + + var handlers:DiscordEventHandlers = DiscordEventHandlers.create(); + handlers.ready = cpp.Function.fromStaticFunction(onReady); + handlers.disconnected = cpp.Function.fromStaticFunction(onDisconnected); + handlers.errored = cpp.Function.fromStaticFunction(onError); + Discord.Initialize(id, cpp.RawPointer.addressOf(handlers), 1, null); + #end + + return currentID = id; + } + + public static function shutdown() + { ready = false; - - DiscordRpc.start({ - clientID: id, - onReady: function() { - Logs.trace('Discord RPC started'); - ready = true; - }, - onError: onError, - onDisconnected: onDisconnected - }); - currentID = id; - - #end - } - - public static function shutdown() { #if DISCORD_RPC - DiscordRpc.shutdown(); + Discord.Shutdown(); #end } - // HANDLERS #if DISCORD_RPC - static function onError(_code:Int, _message:String) { - Logs.trace('Discord RPC Error: ${_message} (Code: $_code)', ERROR); + private static function onReady(request:cpp.RawConstPointer):Void + { + var requestPtr:cpp.Star = cpp.ConstPointer.fromRaw(request).ptr; + + user = new DUser(); + user.init(requestPtr); + + Logs.trace('(Discord) Connected to User (${user.tag})'); + + ready = true; } - static function onDisconnected(_code:Int, _message:String) { - Logs.trace('Discord RPC Disconnected: ${_message} (Code: $_code)', WARNING); + private static function onDisconnected(errorCode:Int, message:cpp.ConstCharStar):Void + { + Sys.println('Discord: Disconnected ($errorCode: ${cast (message, String)})'); + } + + private static function onError(errorCode:Int, message:cpp.ConstCharStar):Void + { + Sys.println('Discord: Error ($errorCode: ${cast (message, String)})'); } #end } -typedef DiscordJson = { +typedef DiscordJson = +{ var ?clientID:String; var ?logoKey:String; var ?logoText:String; -} \ No newline at end of file +} + +@:noCustomClass +final class DUser +{ + /** + * The username + discriminator if they have it + **/ + public var tag:String; + + /** + * The user id, aka 860561967383445535 + **/ + public var userId:String; + + /** + * The user's username + **/ + public var username:String; + + /** + * The #number from before discord changed to usernames only, if the user has changed to a username them its just a 0 + **/ + public var discriminator:Int; + + /** + * The user's avatar filename + **/ + public var avatar:String; + + public function new() {} + public function init(userData:cpp.Star) + { + userId = userData.userId; + username = userData.username; + discriminator = Std.parseInt(userData.discriminator); + avatar = userData.avatar; + + if (discriminator != 0) + tag = '${username}#${discriminator}'; + else + tag = '${username}'; + } + + /** + * Calling this function gets the BitmapData of the user + **/ + public function getAvatar(size:Int = 256):BitmapData + return BitmapData.fromBytes(HttpUtil.requestBytes('https://cdn.discordapp.com/avatars/$userId/$avatar.png?size=$size')); +} + +typedef DPresence = +{ + var ?state:String; /* max 128 bytes */ + var ?details:String; /* max 128 bytes */ + var ?startTimestamp:OneOfTwo; + var ?endTimestamp:OneOfTwo; + var ?largeImageKey:String; /* max 32 bytes */ + var ?largeImageText:String; /* max 128 bytes */ + var ?smallImageKey:String; /* max 32 bytes */ + var ?smallImageText:String; /* max 128 bytes */ + var ?partyId:String; /* max 128 bytes */ + var ?partySize:Int; + var ?partyMax:Int; + var ?partyPrivacy:Int; + var ?matchSecret:String; /* max 128 bytes */ + var ?joinSecret:String; /* max 128 bytes */ + var ?spectateSecret:String; /* max 128 bytes */ + var ?instance:OneOfTwo; +} diff --git a/source/funkin/backend/utils/HttpUtil.hx b/source/funkin/backend/utils/HttpUtil.hx new file mode 100644 index 00000000..1edbbfd2 --- /dev/null +++ b/source/funkin/backend/utils/HttpUtil.hx @@ -0,0 +1,71 @@ +package funkin.backend.utils; + +import haxe.Http; + +class HttpUtil +{ + public static var userAgent:String = "request"; + public static function requestText(url:String) + { + var r = null; + var h = new Http(url); + h.setHeader("User-Agent", userAgent); + + h.onStatus = function(s) + { + if (isRedirect(s)) + r = requestText(h.responseHeaders.get("Location")); + }; + + h.onData = function(d) + { + if (r == null) + r = d; + } + h.onError = function(e) + { + throw e; + } + + h.request(false); + return r; + } + + public static function requestBytes(url:String) + { + var r = null; + var h = new Http(url); + h.setHeader("User-Agent", userAgent); + + h.onStatus = function(s) + { + if (isRedirect(s)) + r = requestBytes(h.responseHeaders.get("Location")); + }; + + h.onBytes = function(d) + { + if (r == null) + r = d; + } + h.onError = function(e) + { + throw e; + } + + h.request(false); + return r; + } + + private static function isRedirect(status:Int):Bool + { + switch (status) + { + // 301: Moved Permanently, 302: Found (Moved Temporarily), 307: Temporary Redirect, 308: Permanent Redirect - Nex + case 301 | 302 | 307 | 308: + trace("Redirected with status code: " + status); + return true; + } + return false; + } +} diff --git a/source/funkin/game/NoteGroup.hx b/source/funkin/game/NoteGroup.hx index 97b34da6..0d45a41f 100644 --- a/source/funkin/game/NoteGroup.hx +++ b/source/funkin/game/NoteGroup.hx @@ -106,6 +106,7 @@ class NoteGroup extends FlxTypedGroup { if (members == null) return null; + // TODO: maybe lastIndexOf var index:Int = members.indexOfFromLast(Object); if (index < 0) diff --git a/source/funkin/options/type/GithubIconOption.hx b/source/funkin/options/type/GithubIconOption.hx index cbbef1ed..7f41b8d4 100644 --- a/source/funkin/options/type/GithubIconOption.hx +++ b/source/funkin/options/type/GithubIconOption.hx @@ -57,7 +57,7 @@ class GithubUserIcon extends FlxSprite var bytes = null; if(unfLink) { - try bytes = GitHub.__requestBytesOnGitHubServers('${user.avatar_url}?size=$size') + try bytes = HttpUtil.requestBytes('${user.avatar_url}?size=$size') catch(e) Logs.traceColored([Logs.logText('Failed to download github pfp for ${user.login}: ${CoolUtil.removeIP(e.message)} - (Retrying using the api..)', RED)], ERROR); if(bytes != null) { @@ -68,7 +68,7 @@ class GithubUserIcon extends FlxSprite if(planB) { if(unfLink) user = GitHub.getUser(user.login, function(e) Logs.traceColored([Logs.logText('Failed to download github user info for ${user.login}: ${CoolUtil.removeIP(e.message)}', RED)], ERROR)); // Api part - Nex - try bytes = GitHub.__requestBytesOnGitHubServers('${user.avatar_url}&size=$size') + try bytes = HttpUtil.requestBytes('${user.avatar_url}&size=$size') catch(e) Logs.traceColored([Logs.logText('Failed to download github pfp for ${user.login}: ${CoolUtil.removeIP(e.message)}', RED)], ERROR); if(bytes != null) bmap = BitmapData.fromBytes(bytes); From 7dd24bdead72b2002b71fd75fd95202fb824d795 Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sat, 23 Mar 2024 01:54:26 +0100 Subject: [PATCH 02/21] Improved Discord Util --- source/funkin/backend/utils/DiscordUtil.hx | 55 ++++++++++++---------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index 733790fa..03c649d2 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -19,6 +19,7 @@ class DiscordUtil public static var currentID(default, set):String = null; public static var discordThread:#if DISCORD_RPC Thread #else Dynamic #end = null; public static var ready:Bool = false; + private static var stopThread:Bool = false; public static var user:#if DISCORD_RPC DUser #else Dynamic #end = null; public static var lastPresence:#if DISCORD_RPC DPresence #else Dynamic #end = null; @@ -33,7 +34,7 @@ class DiscordUtil { while (true) { - while (ready) + while (!stopThread) { #if DISCORD_DISABLE_IO_THREAD Discord.UpdateConnection(); @@ -62,6 +63,10 @@ class DiscordUtil catch (e) Logs.trace('Couldn\'t load Discord RPC configuration: ${e.toString()}', ERROR); } + else + { + config = {}; + } config.logoKey = config.logoKey.getDefault("icon"); config.logoText = config.logoText.getDefault(Application.current.meta.get('title')); @@ -135,26 +140,6 @@ class DiscordUtil var dp:DiscordRichPresence = DiscordRichPresence.create(); // TODO: make this use a reflection-like macro - // strings - /*if(data.state != null) dp.state = fixString(data.state); - if(data.details != null) dp.details = fixString(data.details); - if(data.largeImageKey != null) dp.largeImageKey = fixString(data.largeImageKey); - if(data.largeImageText != null) dp.largeImageText = fixString(data.largeImageText); - if(data.smallImageKey != null) dp.smallImageKey = fixString(data.smallImageKey); - if(data.smallImageText != null) dp.smallImageText = fixString(data.smallImageText); - if(data.partyId != null) dp.partyId = fixString(data.partyId); - if(data.matchSecret != null) dp.matchSecret = fixString(data.matchSecret); - if(data.joinSecret != null) dp.joinSecret = fixString(data.joinSecret); - if(data.spectateSecret != null) dp.spectateSecret = fixString(data.spectateSecret); - - // other - if(data.startTimestamp != null) dp.startTimestamp = data.startTimestamp; - if(data.endTimestamp != null) dp.endTimestamp = data.endTimestamp; - if(data.partySize != null) dp.partySize = data.partySize; - if(data.partyMax != null) dp.partyMax = data.partyMax; - if(data.partyPrivacy != null) dp.partyPrivacy = data.partyPrivacy; - if(data.instance != null) dp.instance = data.instance; */ - Utils.safeSetWrapper(dp.state, data.state, fixString); Utils.safeSetWrapper(dp.details, data.details, fixString); Utils.safeSet(dp.startTimestamp, data.startTimestamp); @@ -189,6 +174,7 @@ class DiscordUtil handlers.disconnected = cpp.Function.fromStaticFunction(onDisconnected); handlers.errored = cpp.Function.fromStaticFunction(onError); Discord.Initialize(id, cpp.RawPointer.addressOf(handlers), 1, null); + stopThread = false; #end return currentID = id; @@ -197,6 +183,7 @@ class DiscordUtil public static function shutdown() { ready = false; + stopThread = true; #if DISCORD_RPC Discord.Shutdown(); #end @@ -211,19 +198,34 @@ class DiscordUtil user = new DUser(); user.init(requestPtr); - Logs.trace('(Discord) Connected to User (${user.tag})'); + Logs.traceColored([ + Logs.logText("[Discord] ", BLUE), + Logs.logText("Connected to User ("), + Logs.logText(user.tag, GRAY), + Logs.logText(")") + ], INFO); ready = true; } private static function onDisconnected(errorCode:Int, message:cpp.ConstCharStar):Void { - Sys.println('Discord: Disconnected ($errorCode: ${cast (message, String)})'); + Logs.traceColored([ + Logs.logText("[Discord] ", BLUE), + Logs.logText("Disconnected ("), + Logs.logText('$errorCode: ${cast (message, String)}', RED), + Logs.logText(")") + ], INFO); } private static function onError(errorCode:Int, message:cpp.ConstCharStar):Void { - Sys.println('Discord: Error ($errorCode: ${cast (message, String)})'); + Logs.traceColored([ + Logs.logText("[Discord] ", BLUE), + Logs.logText("Error ("), + Logs.logText('$errorCode: ${cast (message, String)}', RED), + Logs.logText(")") + ], ERROR); } #end } @@ -263,7 +265,10 @@ final class DUser **/ public var avatar:String; - public function new() {} + public function new() + { + } + public function init(userData:cpp.Star) { userId = userData.userId; From db8aacfd5644199af33ea6cf352101a59caeb89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sat, 23 Mar 2024 03:44:50 +0100 Subject: [PATCH 03/21] handlers structure --- source/funkin/backend/utils/DiscordUtil.hx | 66 ++++++++++++++++++++-- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index 03c649d2..a3aa43de 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -23,11 +23,13 @@ class DiscordUtil public static var user:#if DISCORD_RPC DUser #else Dynamic #end = null; public static var lastPresence:#if DISCORD_RPC DPresence #else Dynamic #end = null; + public static var events:#if DISCORD_RPC DEvents #else Dynamic #end = null; public static var config:#if DISCORD_RPC DiscordJson #else Dynamic #end = null; public static function init() { #if DISCORD_RPC + events = {}; reloadJsonData(); discordThread = Thread.create(function() @@ -173,6 +175,9 @@ class DiscordUtil handlers.ready = cpp.Function.fromStaticFunction(onReady); handlers.disconnected = cpp.Function.fromStaticFunction(onDisconnected); handlers.errored = cpp.Function.fromStaticFunction(onError); + handlers.joinGame = cpp.Function.fromStaticFunction(onJoin); + handlers.joinRequest = cpp.Function.fromStaticFunction(onJoinReq); + handlers.spectateGame = cpp.Function.fromStaticFunction(onSpectate); Discord.Initialize(id, cpp.RawPointer.addressOf(handlers), 1, null); stopThread = false; #end @@ -193,10 +198,8 @@ class DiscordUtil #if DISCORD_RPC private static function onReady(request:cpp.RawConstPointer):Void { - var requestPtr:cpp.Star = cpp.ConstPointer.fromRaw(request).ptr; - user = new DUser(); - user.init(requestPtr); + user.init(cpp.ConstPointer.fromRaw(request).ptr); Logs.traceColored([ Logs.logText("[Discord] ", BLUE), @@ -206,26 +209,69 @@ class DiscordUtil ], INFO); ready = true; + + if(events.ready != null) events.ready(user); } private static function onDisconnected(errorCode:Int, message:cpp.ConstCharStar):Void { + var finalMsg:String = cast (message, String); + Logs.traceColored([ Logs.logText("[Discord] ", BLUE), Logs.logText("Disconnected ("), - Logs.logText('$errorCode: ${cast (message, String)}', RED), + Logs.logText('$errorCode: $finalMsg', RED), Logs.logText(")") ], INFO); + + if(events.disconnected != null) events.disconnected(errorCode, finalMsg); } private static function onError(errorCode:Int, message:cpp.ConstCharStar):Void { + var finalMsg:String = cast (message, String); + Logs.traceColored([ Logs.logText("[Discord] ", BLUE), Logs.logText("Error ("), - Logs.logText('$errorCode: ${cast (message, String)}', RED), + Logs.logText('$errorCode: $finalMsg', RED), Logs.logText(")") ], ERROR); + + if(events.errored != null) events.errored(errorCode, finalMsg); + } + + private static function onJoin(joinSecret:cpp.ConstCharStar):Void + { + Logs.traceColored([ + Logs.logText("[Discord] ", BLUE), + Logs.logText("Someone has just joined", GREEN) + ], INFO); + + if(events.joinGame != null) events.joinGame(cast (joinSecret, String)); + } + + private static function onSpectate(spectateSecret:cpp.ConstCharStar):Void + { + Logs.traceColored([ + Logs.logText("[Discord] ", BLUE), + Logs.logText("Someone started spectating your game", YELLOW) + ], INFO); + + if(events.spectateGame != null) events.spectateGame(cast (spectateSecret, String)); + } + + private static function onJoinReq(request:cpp.RawConstPointer):Void + { + Logs.traceColored([ + Logs.logText("[Discord] ", BLUE), + Logs.logText("Someone has just requested to join", YELLOW) + ], WARNING); + + if(events.joinRequest == null) return; + var req:DUser = new DUser(); + req.init(cpp.ConstPointer.fromRaw(request).ptr); + events.joinRequest(req); } #end } @@ -308,3 +354,13 @@ typedef DPresence = var ?spectateSecret:String; /* max 128 bytes */ var ?instance:OneOfTwo; } + +typedef DEvents = +{ + var ?ready:DUser->Void; + var ?disconnected:(errorCode:Int, message:String)->Void; + var ?errored:(errorCode:Int, message:String)->Void; + var ?joinGame:String->Void; + var ?spectateGame:String->Void; + var ?joinRequest:DUser->Void; +} \ No newline at end of file From a8142457205ac23cf0f69ce5c5e42092b0836a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sat, 23 Mar 2024 13:22:20 +0100 Subject: [PATCH 04/21] discord scripts Co-Authored-By: Ne_Eo --- .../funkin/backend/scripting/GlobalScript.hx | 6 +- source/funkin/backend/utils/DiscordUtil.hx | 130 +++++++++++++----- 2 files changed, 100 insertions(+), 36 deletions(-) diff --git a/source/funkin/backend/scripting/GlobalScript.hx b/source/funkin/backend/scripting/GlobalScript.hx index 34da69b5..ec0c0083 100644 --- a/source/funkin/backend/scripting/GlobalScript.hx +++ b/source/funkin/backend/scripting/GlobalScript.hx @@ -79,12 +79,14 @@ class GlobalScript { } public static function event(name:String, event:T):T { - if (scripts != null) scripts.call(name, [event]); + if (scripts != null) + scripts.event(name, event); return event; } public static function call(name:String, ?args:Array) { - if (scripts != null) scripts.call(name, args); + if (scripts != null) + scripts.call(name, args); } public static function onModSwitch(newMod:String) { call("destroy"); diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index a3aa43de..d598e11c 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -1,9 +1,11 @@ package funkin.backend.utils; +import funkin.backend.scripting.events.DiscordPresenceUpdateEvent; +import funkin.backend.scripting.events.CancellableEvent; +import funkin.backend.scripting.*; // lazy import flixel.util.typeLimit.OneOfTwo; import openfl.display.BitmapData; import funkin.backend.system.macros.Utils; -import funkin.backend.scripting.events.DiscordPresenceUpdateEvent; import haxe.Json; import flixel.sound.FlxSound; #if DISCORD_RPC @@ -26,6 +28,8 @@ class DiscordUtil public static var events:#if DISCORD_RPC DEvents #else Dynamic #end = null; public static var config:#if DISCORD_RPC DiscordJson #else Dynamic #end = null; + public static var scripts:ScriptPack; + public static function init() { #if DISCORD_RPC @@ -77,6 +81,39 @@ class DiscordUtil #end } + public static function event(name:String, event:T):T + { + if (scripts != null) + scripts.event(name, event); + return event; + } + + public static function call(name:String, ?args:Array) + { + if (scripts != null) + scripts.call(name, args); + } + + public static function loadScript() + { + if(scripts != null) { + call("destroy"); + scripts = FlxDestroyUtil.destroy(scripts); + } + scripts = new ScriptPack("DiscordScript"); + for (i in funkin.backend.assets.ModsFolder.getLoadedMods()) + { + var path = Paths.script('data/discord/LIB_$i'); + var script = Script.create(path); + if (script is DummyScript) + continue; + + script.remappedNames.set(script.fileName, '$i:${script.fileName}'); + scripts.add(script); + script.load(); + } + } + public static function changePresence(details:String, state:String, ?smallImageKey:String) { #if DISCORD_RPC @@ -132,12 +169,15 @@ class DiscordUtil if (data.largeImageText == null) data.largeImageText = config.logoText; + var evt = EventManager.get(DiscordPresenceUpdateEvent).recycle(data); #if GLOBAL_SCRIPT - var event = funkin.backend.scripting.GlobalScript.event("onDiscordPresenceUpdate", EventManager.get(DiscordPresenceUpdateEvent).recycle(data)); - if (event.cancelled) - return; - data = event.presence; + // kept for "backwards compat" + funkin.backend.scripting.GlobalScript.event("onDiscordPresenceUpdate", evt); #end + event("onDiscordPresenceUpdate", evt); + if (evt.cancelled) + return; + data = evt.presence; lastPresence = data; var dp:DiscordRichPresence = DiscordRichPresence.create(); @@ -180,6 +220,8 @@ class DiscordUtil handlers.spectateGame = cpp.Function.fromStaticFunction(onSpectate); Discord.Initialize(id, cpp.RawPointer.addressOf(handlers), 1, null); stopThread = false; + + loadScript(); #end return currentID = id; @@ -192,14 +234,16 @@ class DiscordUtil #if DISCORD_RPC Discord.Shutdown(); #end + + call("destroy"); + scripts = FlxDestroyUtil.destroy(scripts); } // HANDLERS #if DISCORD_RPC private static function onReady(request:cpp.RawConstPointer):Void { - user = new DUser(); - user.init(cpp.ConstPointer.fromRaw(request).ptr); + user = DUser.initRaw(request); Logs.traceColored([ Logs.logText("[Discord] ", BLUE), @@ -210,12 +254,13 @@ class DiscordUtil ready = true; - if(events.ready != null) events.ready(user); + // if(events.ready != null) events.ready(user); + call("onReady", [user]); } private static function onDisconnected(errorCode:Int, message:cpp.ConstCharStar):Void { - var finalMsg:String = cast (message, String); + var finalMsg:String = cast(message, String); Logs.traceColored([ Logs.logText("[Discord] ", BLUE), @@ -224,12 +269,15 @@ class DiscordUtil Logs.logText(")") ], INFO); - if(events.disconnected != null) events.disconnected(errorCode, finalMsg); + if (events.disconnected != null) + events.disconnected(errorCode, finalMsg); + + call("onReady", [errorCode, cast(finalMsg, String)]); } private static function onError(errorCode:Int, message:cpp.ConstCharStar):Void { - var finalMsg:String = cast (message, String); + var finalMsg:String = cast(message, String); Logs.traceColored([ Logs.logText("[Discord] ", BLUE), @@ -238,17 +286,20 @@ class DiscordUtil Logs.logText(")") ], ERROR); - if(events.errored != null) events.errored(errorCode, finalMsg); + if (events.errored != null) + events.errored(errorCode, finalMsg); + + call("onError", [errorCode, cast(finalMsg, String)]); } private static function onJoin(joinSecret:cpp.ConstCharStar):Void { - Logs.traceColored([ - Logs.logText("[Discord] ", BLUE), - Logs.logText("Someone has just joined", GREEN) - ], INFO); + Logs.traceColored([Logs.logText("[Discord] ", BLUE), Logs.logText("Someone has just joined", GREEN)], INFO); - if(events.joinGame != null) events.joinGame(cast (joinSecret, String)); + if (events.joinGame != null) + events.joinGame(cast(joinSecret, String)); + + call("onJoinGame", [cast(joinSecret, String)]); } private static function onSpectate(spectateSecret:cpp.ConstCharStar):Void @@ -258,7 +309,10 @@ class DiscordUtil Logs.logText("Someone started spectating your game", YELLOW) ], INFO); - if(events.spectateGame != null) events.spectateGame(cast (spectateSecret, String)); + if (events.spectateGame != null) + events.spectateGame(cast(spectateSecret, String)); + + call("onJoinGame", [cast(spectateSecret, String)]); } private static function onJoinReq(request:cpp.RawConstPointer):Void @@ -268,10 +322,11 @@ class DiscordUtil Logs.logText("Someone has just requested to join", YELLOW) ], WARNING); - if(events.joinRequest == null) return; - var req:DUser = new DUser(); - req.init(cpp.ConstPointer.fromRaw(request).ptr); - events.joinRequest(req); + var req:DUser = DUser.initRaw(request); + if (events.joinRequest != null) + events.joinRequest(req); + + call("onJoinRequest", [req]); } #end } @@ -311,21 +366,28 @@ final class DUser **/ public var avatar:String; - public function new() + private function new() { } - public function init(userData:cpp.Star) + public static function initRaw(req:cpp.RawConstPointer) { - userId = userData.userId; - username = userData.username; - discriminator = Std.parseInt(userData.discriminator); - avatar = userData.avatar; + return init(cpp.ConstPointer.fromRaw(req).ptr); + } - if (discriminator != 0) - tag = '${username}#${discriminator}'; + public static function init(userData:cpp.Star) + { + var d = new DUser(); + d.userId = userData.userId; + d.username = userData.username; + d.discriminator = Std.parseInt(userData.discriminator); + d.avatar = userData.avatar; + + if (d.discriminator != 0) + d.tag = '${d.username}#${d.discriminator}'; else - tag = '${username}'; + d.tag = '${d.username}'; + return d; } /** @@ -358,9 +420,9 @@ typedef DPresence = typedef DEvents = { var ?ready:DUser->Void; - var ?disconnected:(errorCode:Int, message:String)->Void; - var ?errored:(errorCode:Int, message:String)->Void; + var ?disconnected:(errorCode:Int, message:String) -> Void; + var ?errored:(errorCode:Int, message:String) -> Void; var ?joinGame:String->Void; var ?spectateGame:String->Void; var ?joinRequest:DUser->Void; -} \ No newline at end of file +} From 34ce2d21a8a93134d71822370052f75323b02f46 Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sat, 23 Mar 2024 13:26:10 +0100 Subject: [PATCH 05/21] Fix version warning --- project.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/project.xml b/project.xml index 6f26ce30..a62eb449 100644 --- a/project.xml +++ b/project.xml @@ -174,6 +174,7 @@ + From 0754b2e78fce11b70a96ab3264ebab77a882adcb Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sat, 23 Mar 2024 13:33:08 +0100 Subject: [PATCH 06/21] Oops --- .../funkin/backend/scripting/GlobalScript.hx | 3 +- source/funkin/backend/utils/DiscordUtil.hx | 30 +++++++------------ 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/source/funkin/backend/scripting/GlobalScript.hx b/source/funkin/backend/scripting/GlobalScript.hx index ec0c0083..5c037aec 100644 --- a/source/funkin/backend/scripting/GlobalScript.hx +++ b/source/funkin/backend/scripting/GlobalScript.hx @@ -95,7 +95,8 @@ class GlobalScript { for (i in funkin.backend.assets.ModsFolder.getLoadedMods()) { var path = Paths.script('data/global/LIB_$i'); var script = Script.create(path); - if (script is DummyScript) continue; + if (script is DummyScript) + continue; script.remappedNames.set(script.fileName, '$i:${script.fileName}'); scripts.add(script); script.load(); diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index d598e11c..c6825b4a 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -28,7 +28,7 @@ class DiscordUtil public static var events:#if DISCORD_RPC DEvents #else Dynamic #end = null; public static var config:#if DISCORD_RPC DiscordJson #else Dynamic #end = null; - public static var scripts:ScriptPack; + public static var script:Script; public static function init() { @@ -83,35 +83,25 @@ class DiscordUtil public static function event(name:String, event:T):T { - if (scripts != null) - scripts.event(name, event); + if (script != null) + script.call(name, [event]); return event; } public static function call(name:String, ?args:Array) { - if (scripts != null) - scripts.call(name, args); + if (script != null) + script.call(name, args); } public static function loadScript() { - if(scripts != null) { + if(script != null) { call("destroy"); - scripts = FlxDestroyUtil.destroy(scripts); - } - scripts = new ScriptPack("DiscordScript"); - for (i in funkin.backend.assets.ModsFolder.getLoadedMods()) - { - var path = Paths.script('data/discord/LIB_$i'); - var script = Script.create(path); - if (script is DummyScript) - continue; - - script.remappedNames.set(script.fileName, '$i:${script.fileName}'); - scripts.add(script); - script.load(); + script = FlxDestroyUtil.destroy(script); } + script = Script.create(Paths.script('data/discord')); + script.load(); } public static function changePresence(details:String, state:String, ?smallImageKey:String) @@ -236,7 +226,7 @@ class DiscordUtil #end call("destroy"); - scripts = FlxDestroyUtil.destroy(scripts); + script = FlxDestroyUtil.destroy(script); } // HANDLERS From b7b1441e316103ec21d511ee1734a3bd51e92350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sat, 23 Mar 2024 21:50:19 +0100 Subject: [PATCH 07/21] fixin --- project.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/project.xml b/project.xml index a62eb449..77ae6af6 100644 --- a/project.xml +++ b/project.xml @@ -161,6 +161,13 @@ + + + + + + + @@ -173,10 +180,6 @@ - - - -
From 5eac25a5418886060eed53c2abe80c39ae3ed3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sat, 23 Mar 2024 23:34:52 +0100 Subject: [PATCH 08/21] softcoded rpc calls Co-Authored-By: Ne_Eo --- assets/data/discord.hx | 40 +++++++++++++++++++ source/funkin/backend/utils/DiscordUtil.hx | 15 +++++++ .../editors/character/CharacterEditor.hx | 4 +- .../editors/character/CharacterSelection.hx | 2 + source/funkin/editors/charter/Charter.hx | 2 + .../editors/charter/CharterSelection.hx | 2 + source/funkin/game/GameOverSubstate.hx | 3 +- source/funkin/game/PlayState.hx | 2 +- source/funkin/menus/FreeplayState.hx | 2 +- source/funkin/menus/MainMenuState.hx | 2 +- source/funkin/menus/StoryMenuState.hx | 2 +- source/funkin/menus/TitleState.hx | 2 + source/funkin/menus/credits/CreditsMain.hx | 2 + source/funkin/options/OptionsMenu.hx | 2 + 14 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 assets/data/discord.hx diff --git a/assets/data/discord.hx b/assets/data/discord.hx new file mode 100644 index 00000000..d528134b --- /dev/null +++ b/assets/data/discord.hx @@ -0,0 +1,40 @@ +function onGameOver() { + changePresence('Game Over', PlayState.SONG.meta.displayName + " (" + PlayState.difficulty + ")"); +} + +function onPlayStateUpdate() { + // Setting parent to make code cleaner + var old = __script__.interp.scriptObject; + __script__.interp.scriptObject = PlayState.instance; + + DiscordUtil.changeSongPresence(detailsText, (paused ? "Paused - " : "") + SONG.meta.displayName + " (" + difficulty + ")", inst, getIconRPC()); + + __script__.interp.scriptObject = old; +} + +function onMenuLoaded(name:String) { + // Name is either "Main Menu", "Freeplay", "Title Screen", "Options Menu", "Credits Menu" + changePresenceSince("In the Menus", null); +} + +function onEditorTreeLoaded(name:String) { + switch(name) { + case "Character Editor": + changePresenceSince("Choosing a Character", null); + case "Chart Editor": + changePresenceSince("Choosing a Chart", null); + case "Stage Editor": + changePresenceSince("Choosing a Stage", null); + } +} + +function onEditorLoaded(name:String, editingThing:String) { + switch(name) { + case "Character Editor": + changePresenceSince("Editing a Character", editingThing); + case "Chart Editor": + changePresenceSince("Editing a Chart", editingThing); + case "Stage Editor": + changePresenceSince("Editing a Stage", editingThing); + } +} \ No newline at end of file diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index c6825b4a..5a85173b 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -101,6 +101,7 @@ class DiscordUtil script = FlxDestroyUtil.destroy(script); } script = Script.create(Paths.script('data/discord')); + script.setParent(DiscordUtil); script.load(); } @@ -137,6 +138,20 @@ class DiscordUtil #end } + public static function changePresenceSince(details:String, state:String, ?smallImageKey:String, ?offset:Float = 0) + { + #if DISCORD_RPC + var start:Float = Date.now().getTime() + offset; + + changePresenceAdvanced({ + state: state, + details: details, + smallImageKey: smallImageKey, + startTimestamp: Std.int(start / 1000) + }); + #end + } + @:noCompletion public static function fixString(str:String) { return new cpp.ConstCharStar(cast(str, String)); diff --git a/source/funkin/editors/character/CharacterEditor.hx b/source/funkin/editors/character/CharacterEditor.hx index 8c5cf9c7..359ef24d 100644 --- a/source/funkin/editors/character/CharacterEditor.hx +++ b/source/funkin/editors/character/CharacterEditor.hx @@ -224,7 +224,7 @@ class CharacterEditor extends UIState { FlxG.cameras.add(uiCamera); FlxG.cameras.add(animsCamera); - character = new Character(0,0,__character, false, false); + character = new Character(0,0, __character, false, false); character.debugMode = true; character.cameras = [charCamera]; @@ -257,6 +257,8 @@ class CharacterEditor extends UIState { Framerate.memoryCounter.alpha = 0.4; Framerate.codenameBuildField.alpha = 0.4; } + + DiscordUtil.call("onEditorLoaded", ["Character Editor", __character]); } override function destroy() { diff --git a/source/funkin/editors/character/CharacterSelection.hx b/source/funkin/editors/character/CharacterSelection.hx index 9d1a60ed..817acf29 100644 --- a/source/funkin/editors/character/CharacterSelection.hx +++ b/source/funkin/editors/character/CharacterSelection.hx @@ -33,6 +33,8 @@ class CharacterSelection extends EditorTreeMenu })); main = new OptionsScreen("Character Editor", "Select a character to edit", list); + + DiscordUtil.call("onEditorTreeLoaded", ["Character Editor"]); } override function createPost() { diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 34671758..21c3c2b7 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -490,6 +490,8 @@ class Charter extends UIState { Framerate.codenameBuildField.alpha = 0.4; } updateDisplaySprites(); + + DiscordUtil.call("onEditorLoaded", ["Chart Editor", __song + " (" + __diff + ")"]); } override function destroy() { diff --git a/source/funkin/editors/charter/CharterSelection.hx b/source/funkin/editors/charter/CharterSelection.hx index b0957997..6fd97bdc 100644 --- a/source/funkin/editors/charter/CharterSelection.hx +++ b/source/funkin/editors/charter/CharterSelection.hx @@ -46,6 +46,8 @@ class CharterSelection extends EditorTreeMenu { })); main = new OptionsScreen("Chart Editor", "Select a song to modify the charts from.", list); + + DiscordUtil.call("onEditorTreeLoaded", ["Chart Editor"]); } override function createPost() { diff --git a/source/funkin/game/GameOverSubstate.hx b/source/funkin/game/GameOverSubstate.hx index 3d119f02..4868b130 100644 --- a/source/funkin/game/GameOverSubstate.hx +++ b/source/funkin/game/GameOverSubstate.hx @@ -87,8 +87,7 @@ class GameOverSubstate extends MusicBeatSubstate lossSFX = FlxG.sound.play(Paths.sound(lossSFXName)); Conductor.changeBPM(gameOverSongBPM); - DiscordUtil.changePresence('Game Over', PlayState.SONG.meta.displayName + " (" + PlayState.difficulty + ")"); - + DiscordUtil.call("onGameOver", []); gameoverScript.call("postCreate"); } diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index c7364225..91e977a6 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -784,7 +784,7 @@ class PlayState extends MusicBeatState * This function is dynamic, which means you can do `updateDiscordPresence = function() {}` in scripts. */ public dynamic function updateDiscordPresence() - DiscordUtil.changeSongPresence(detailsText, (paused ? "Paused - " : "") + SONG.meta.displayName + " (" + difficulty + ")", inst, getIconRPC()); + DiscordUtil.call("onPlayStateUpdate", []); /** * Starts a cutscene. diff --git a/source/funkin/menus/FreeplayState.hx b/source/funkin/menus/FreeplayState.hx index 0a6f3493..7ca66b02 100644 --- a/source/funkin/menus/FreeplayState.hx +++ b/source/funkin/menus/FreeplayState.hx @@ -116,7 +116,7 @@ class FreeplayState extends MusicBeatState } } - DiscordUtil.changePresence("In the Menus", null); + DiscordUtil.call("onMenuLoaded", ["Freeplay"]); super.create(); diff --git a/source/funkin/menus/MainMenuState.hx b/source/funkin/menus/MainMenuState.hx index 03e3bd8b..b17e9db6 100644 --- a/source/funkin/menus/MainMenuState.hx +++ b/source/funkin/menus/MainMenuState.hx @@ -32,7 +32,7 @@ class MainMenuState extends MusicBeatState { super.create(); - DiscordUtil.changePresence("In the Menus", null); + DiscordUtil.call("onMenuLoaded", ["Main Menu"]); CoolUtil.playMenuSong(); diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx index 6d9e27f2..384118e5 100644 --- a/source/funkin/menus/StoryMenuState.hx +++ b/source/funkin/menus/StoryMenuState.hx @@ -116,7 +116,7 @@ class StoryMenuState extends MusicBeatState { changeWeek(0, true); - DiscordUtil.changePresence("In the Menus", null); + DiscordUtil.call("onMenuLoaded", ["Story Menu"]); CoolUtil.playMenuSong(); } diff --git a/source/funkin/menus/TitleState.hx b/source/funkin/menus/TitleState.hx index 491bc65a..4aca30db 100644 --- a/source/funkin/menus/TitleState.hx +++ b/source/funkin/menus/TitleState.hx @@ -36,6 +36,8 @@ class TitleState extends MusicBeatState startIntro(); super.create(); + + DiscordUtil.call("onMenuLoaded", ["Title Screen"]); } var logoBl:FlxSprite; diff --git a/source/funkin/menus/credits/CreditsMain.hx b/source/funkin/menus/credits/CreditsMain.hx index 5dd16aff..56507274 100644 --- a/source/funkin/menus/credits/CreditsMain.hx +++ b/source/funkin/menus/credits/CreditsMain.hx @@ -43,6 +43,8 @@ class CreditsMain extends TreeMenu { main = new OptionsScreen('Credits', 'The people who made this possible!', selectables); super.create(); + + DiscordUtil.call("onMenuLoaded", ["Credits Menu"]); } /** diff --git a/source/funkin/options/OptionsMenu.hx b/source/funkin/options/OptionsMenu.hx index 5b786e10..f9232e13 100644 --- a/source/funkin/options/OptionsMenu.hx +++ b/source/funkin/options/OptionsMenu.hx @@ -37,6 +37,8 @@ class OptionsMenu extends TreeMenu { CoolUtil.playMenuSong(); + DiscordUtil.call("onMenuLoaded", ["Options Menu"]); + var bg:FlxSprite = new FlxSprite(-80).loadAnimatedGraphic(Paths.image('menus/menuBGBlue')); // bg.scrollFactor.set(); bg.scale.set(1.15, 1.15); From 8db8aca56564cbeba98eaba53831d4827a69f1fa Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 00:01:36 +0100 Subject: [PATCH 09/21] Fixed discord script --- assets/data/discord.hx | 18 ++++++++------- source/funkin/backend/system/Main.hx | 1 - source/funkin/backend/system/MainState.hx | 2 +- source/funkin/backend/utils/DiscordUtil.hx | 27 ++++++---------------- 4 files changed, 18 insertions(+), 30 deletions(-) diff --git a/assets/data/discord.hx b/assets/data/discord.hx index d528134b..371ea81b 100644 --- a/assets/data/discord.hx +++ b/assets/data/discord.hx @@ -1,5 +1,7 @@ +import funkin.backend.utils.DiscordUtil; + function onGameOver() { - changePresence('Game Over', PlayState.SONG.meta.displayName + " (" + PlayState.difficulty + ")"); + DiscordUtil.changePresence('Game Over', PlayState.SONG.meta.displayName + " (" + PlayState.difficulty + ")"); } function onPlayStateUpdate() { @@ -14,27 +16,27 @@ function onPlayStateUpdate() { function onMenuLoaded(name:String) { // Name is either "Main Menu", "Freeplay", "Title Screen", "Options Menu", "Credits Menu" - changePresenceSince("In the Menus", null); + DiscordUtil.changePresenceSince("In the Menus", null); } function onEditorTreeLoaded(name:String) { switch(name) { case "Character Editor": - changePresenceSince("Choosing a Character", null); + DiscordUtil.changePresenceSince("Choosing a Character", null); case "Chart Editor": - changePresenceSince("Choosing a Chart", null); + DiscordUtil.changePresenceSince("Choosing a Chart", null); case "Stage Editor": - changePresenceSince("Choosing a Stage", null); + DiscordUtil.changePresenceSince("Choosing a Stage", null); } } function onEditorLoaded(name:String, editingThing:String) { switch(name) { case "Character Editor": - changePresenceSince("Editing a Character", editingThing); + DiscordUtil.changePresenceSince("Editing a Character", editingThing); case "Chart Editor": - changePresenceSince("Editing a Chart", editingThing); + DiscordUtil.changePresenceSince("Editing a Chart", editingThing); case "Stage Editor": - changePresenceSince("Editing a Stage", editingThing); + DiscordUtil.changePresenceSince("Editing a Stage", editingThing); } } \ No newline at end of file diff --git a/source/funkin/backend/system/Main.hx b/source/funkin/backend/system/Main.hx index d04d4f3d..cad2266e 100644 --- a/source/funkin/backend/system/Main.hx +++ b/source/funkin/backend/system/Main.hx @@ -120,7 +120,6 @@ class Main extends Sprite ShaderResizeFix.init(); Logs.init(); Paths.init(); - DiscordUtil.init(); #if GLOBAL_SCRIPT funkin.backend.scripting.GlobalScript.init(); #end diff --git a/source/funkin/backend/system/MainState.hx b/source/funkin/backend/system/MainState.hx index e8192fc1..885da7b0 100644 --- a/source/funkin/backend/system/MainState.hx +++ b/source/funkin/backend/system/MainState.hx @@ -55,7 +55,7 @@ class MainState extends FlxState { Main.refreshAssets(); ModsFolder.onModSwitch.dispatch(ModsFolder.currentModFolder); - DiscordUtil.reloadJsonData(); + DiscordUtil.init(); EventsData.reloadEvents(); TitleState.initialized = false; diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index 5a85173b..68f366ee 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -21,11 +21,11 @@ class DiscordUtil public static var currentID(default, set):String = null; public static var discordThread:#if DISCORD_RPC Thread #else Dynamic #end = null; public static var ready:Bool = false; + public static var initialized:Bool = false; private static var stopThread:Bool = false; public static var user:#if DISCORD_RPC DUser #else Dynamic #end = null; public static var lastPresence:#if DISCORD_RPC DPresence #else Dynamic #end = null; - public static var events:#if DISCORD_RPC DEvents #else Dynamic #end = null; public static var config:#if DISCORD_RPC DiscordJson #else Dynamic #end = null; public static var script:Script; @@ -33,8 +33,10 @@ class DiscordUtil public static function init() { #if DISCORD_RPC - events = {}; reloadJsonData(); + if (initialized) + return; + initialized = true; discordThread = Thread.create(function() { @@ -96,12 +98,13 @@ class DiscordUtil public static function loadScript() { - if(script != null) { + if (script != null) + { call("destroy"); script = FlxDestroyUtil.destroy(script); } script = Script.create(Paths.script('data/discord')); - script.setParent(DiscordUtil); + // script.setParent(DiscordUtil); script.load(); } @@ -259,7 +262,6 @@ class DiscordUtil ready = true; - // if(events.ready != null) events.ready(user); call("onReady", [user]); } @@ -274,9 +276,6 @@ class DiscordUtil Logs.logText(")") ], INFO); - if (events.disconnected != null) - events.disconnected(errorCode, finalMsg); - call("onReady", [errorCode, cast(finalMsg, String)]); } @@ -291,9 +290,6 @@ class DiscordUtil Logs.logText(")") ], ERROR); - if (events.errored != null) - events.errored(errorCode, finalMsg); - call("onError", [errorCode, cast(finalMsg, String)]); } @@ -301,9 +297,6 @@ class DiscordUtil { Logs.traceColored([Logs.logText("[Discord] ", BLUE), Logs.logText("Someone has just joined", GREEN)], INFO); - if (events.joinGame != null) - events.joinGame(cast(joinSecret, String)); - call("onJoinGame", [cast(joinSecret, String)]); } @@ -314,9 +307,6 @@ class DiscordUtil Logs.logText("Someone started spectating your game", YELLOW) ], INFO); - if (events.spectateGame != null) - events.spectateGame(cast(spectateSecret, String)); - call("onJoinGame", [cast(spectateSecret, String)]); } @@ -328,9 +318,6 @@ class DiscordUtil ], WARNING); var req:DUser = DUser.initRaw(request); - if (events.joinRequest != null) - events.joinRequest(req); - call("onJoinRequest", [req]); } #end From 1e925f11d3a9766b5a032244ef18730bb2ca907d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sun, 24 Mar 2024 01:19:49 +0100 Subject: [PATCH 10/21] opa --- assets/data/discord.hx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/assets/data/discord.hx b/assets/data/discord.hx index 371ea81b..220efbfa 100644 --- a/assets/data/discord.hx +++ b/assets/data/discord.hx @@ -5,13 +5,12 @@ function onGameOver() { } function onPlayStateUpdate() { - // Setting parent to make code cleaner - var old = __script__.interp.scriptObject; - __script__.interp.scriptObject = PlayState.instance; - - DiscordUtil.changeSongPresence(detailsText, (paused ? "Paused - " : "") + SONG.meta.displayName + " (" + difficulty + ")", inst, getIconRPC()); - - __script__.interp.scriptObject = old; + DiscordUtil.changeSongPresence( + PlayState.instance.detailsText, + (PlayState.instance.paused ? "Paused - " : "") + PlayState.SONG.meta.displayName + " (" + PlayState.difficulty + ")", + PlayState.instance.inst, + PlayState.instance.getIconRPC() + ); } function onMenuLoaded(name:String) { From 9370d5da43f73a6f33744e3bc447b66284302c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sun, 24 Mar 2024 02:07:44 +0100 Subject: [PATCH 11/21] oops --- source/funkin/backend/utils/DiscordUtil.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index 68f366ee..e02a6b74 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -307,7 +307,7 @@ class DiscordUtil Logs.logText("Someone started spectating your game", YELLOW) ], INFO); - call("onJoinGame", [cast(spectateSecret, String)]); + call("onSpectateGame", [cast(spectateSecret, String)]); } private static function onJoinReq(request:cpp.RawConstPointer):Void From 4cc8f277343fea5fb6eb1d1ce585e13a35860fbc Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 04:24:14 +0100 Subject: [PATCH 12/21] Added display names and buttons --- assets/data/discord.hx | 9 ++++ libs.xml | 3 +- source/funkin/backend/utils/DiscordUtil.hx | 57 +++++++++++++++++++--- source/funkin/editors/charter/Charter.hx | 2 +- 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/assets/data/discord.hx b/assets/data/discord.hx index 220efbfa..5aad1856 100644 --- a/assets/data/discord.hx +++ b/assets/data/discord.hx @@ -4,6 +4,15 @@ function onGameOver() { DiscordUtil.changePresence('Game Over', PlayState.SONG.meta.displayName + " (" + PlayState.difficulty + ")"); } +function onDiscordPresenceUpdate(e) { + var data = e.presence; + + if(data.button1Label == null) + data.button1Label = "Codename Engine Discord"; + if(data.button1Url == null) + data.button1Url = "https://discord.gg/2NTCdsQvx4"; +} + function onPlayStateUpdate() { DiscordUtil.changeSongPresence( PlayState.instance.detailsText, diff --git a/libs.xml b/libs.xml index 5afacfc3..95f64aee 100644 --- a/libs.xml +++ b/libs.xml @@ -11,7 +11,8 @@ - + + diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index e02a6b74..e74df162 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -206,6 +206,13 @@ class DiscordUtil Utils.safeSetWrapper(dp.joinSecret, data.joinSecret, fixString); Utils.safeSetWrapper(dp.spectateSecret, data.spectateSecret, fixString); Utils.safeSet(dp.instance, data.instance); + if (data.matchSecret == null && data.joinSecret == null && data.spectateSecret == null) + { + Utils.safeSetWrapper(dp.button1Label, data.button1Label, fixString); + Utils.safeSetWrapper(dp.button1Url, data.button1Url, fixString); + Utils.safeSetWrapper(dp.button2Label, data.button2Label, fixString); + Utils.safeSetWrapper(dp.button2Url, data.button2Url, fixString); + } Discord.UpdatePresence(cpp.RawConstPointer.addressOf(dp)); #end @@ -255,8 +262,8 @@ class DiscordUtil Logs.traceColored([ Logs.logText("[Discord] ", BLUE), - Logs.logText("Connected to User ("), - Logs.logText(user.tag, GRAY), + Logs.logText("Connected to User " + user.globalName + " ("), + Logs.logText(user.handle, GRAY), Logs.logText(")") ], INFO); @@ -285,9 +292,7 @@ class DiscordUtil Logs.traceColored([ Logs.logText("[Discord] ", BLUE), - Logs.logText("Error ("), - Logs.logText('$errorCode: $finalMsg', RED), - Logs.logText(")") + Logs.logText('Error ($errorCode: $finalMsg)', RED) ], ERROR); call("onError", [errorCode, cast(finalMsg, String)]); @@ -336,7 +341,7 @@ final class DUser /** * The username + discriminator if they have it **/ - public var tag:String; + public var handle:String; /** * The user id, aka 860561967383445535 @@ -358,6 +363,26 @@ final class DUser **/ public var avatar:String; + /** + * The user's display name + **/ + public var globalName:String; + + /** + * If the user is a bot or not + **/ + public var bot:Bool; + + /** + * Idk check discord docs + **/ + public var flags:Int; + + /** + * If the user has nitro + **/ + public var premium:NitroType; + private function new() { } @@ -374,11 +399,15 @@ final class DUser d.username = userData.username; d.discriminator = Std.parseInt(userData.discriminator); d.avatar = userData.avatar; + d.globalName = userData.globalName; + d.bot = userData.bot; + d.flags = userData.flags; + d.premium = userData.premium; if (d.discriminator != 0) - d.tag = '${d.username}#${d.discriminator}'; + d.handle = '${d.username}#${d.discriminator}'; else - d.tag = '${d.username}'; + d.handle = '${d.username}'; return d; } @@ -389,6 +418,14 @@ final class DUser return BitmapData.fromBytes(HttpUtil.requestBytes('https://cdn.discordapp.com/avatars/$userId/$avatar.png?size=$size')); } +enum abstract NitroType(Int) to Int from Int +{ + var NONE = 0; + var NITRO_CLASSIC = 1; + var NITRO = 2; + var NITRO_BASIC = 3; +} + typedef DPresence = { var ?state:String; /* max 128 bytes */ @@ -407,6 +444,10 @@ typedef DPresence = var ?joinSecret:String; /* max 128 bytes */ var ?spectateSecret:String; /* max 128 bytes */ var ?instance:OneOfTwo; + var ?button1Label:String; /* max 32 bytes */ + var ?button1Url:String; /* max 512 bytes */ + var ?button2Label:String; /* max 32 bytes */ + var ?button2Url:String; /* max 512 bytes */ } typedef DEvents = diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 21c3c2b7..d7df2ab1 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -530,7 +530,7 @@ class Charter extends UIState { notesGroup.autoSort = false; var noteCount:Int = 0; for (strL in PlayState.SONG.strumLines) - for (note in strL.notes) noteCount++; + noteCount += strL.notes.length; notesGroup.preallocate(noteCount); var notesCreated:Int = 0; From b6374a80a41cf96142c5ed14e712c63044567fae Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 04:33:28 +0100 Subject: [PATCH 13/21] Finishing the rpc update --- source/funkin/backend/utils/DiscordUtil.hx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index e74df162..7593aefc 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -30,6 +30,13 @@ class DiscordUtil public static var script:Script; + // Constants + public static var REPLY_NO:Int = Discord.REPLY_NO; + public static var REPLY_YES:Int = Discord.REPLY_YES; + public static var REPLY_IGNORE:Int = Discord.REPLY_IGNORE; + public static var PARTY_PRIVATE:Int = Discord.PARTY_PRIVATE; + public static var PARTY_PUBLIC:Int = Discord.PARTY_PUBLIC; + public static function init() { #if DISCORD_RPC @@ -218,6 +225,12 @@ class DiscordUtil #end } + public static function clearPresence() { + #if DISCORD_RPC + Discord.ClearPresence(); + #end + } + private static function set_currentID(id:String):String { if (currentID == id) @@ -254,6 +267,13 @@ class DiscordUtil script = FlxDestroyUtil.destroy(script); } + public static function respond(userId:String, reply:Int) + { + #if DISCORD_RPC + Discord.Respond(fixString(userId), reply); + #end + } + // HANDLERS #if DISCORD_RPC private static function onReady(request:cpp.RawConstPointer):Void From f18239494b5a6638682f6383f5174bff1a043942 Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 13:41:27 +0100 Subject: [PATCH 14/21] fix thing --- libs.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs.xml b/libs.xml index 95f64aee..7e7aabb8 100644 --- a/libs.xml +++ b/libs.xml @@ -1,8 +1,8 @@ - - + + @@ -11,7 +11,7 @@ - + From d6201f3df5b4fda57155083c34e7eefaae539e74 Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 15:27:04 +0100 Subject: [PATCH 15/21] Fix stuffs --- libs.xml | 2 +- source/funkin/backend/utils/DiscordUtil.hx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs.xml b/libs.xml index 7e7aabb8..7a82fd43 100644 --- a/libs.xml +++ b/libs.xml @@ -11,7 +11,7 @@ - + diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index 7593aefc..783417e0 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -401,7 +401,7 @@ final class DUser /** * If the user has nitro **/ - public var premium:NitroType; + public var premiumType:NitroType; private function new() { @@ -422,7 +422,7 @@ final class DUser d.globalName = userData.globalName; d.bot = userData.bot; d.flags = userData.flags; - d.premium = userData.premium; + d.premiumType = userData.premiumType; if (d.discriminator != 0) d.handle = '${d.username}#${d.discriminator}'; From 1145ebe7f7412134abfd4ae3bf7ec866e475c3f5 Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 15:45:18 +0100 Subject: [PATCH 16/21] Added beta warning to rpc --- assets/data/discord.hx | 2 +- source/funkin/menus/BetaWarningState.hx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/assets/data/discord.hx b/assets/data/discord.hx index 5aad1856..205f88d6 100644 --- a/assets/data/discord.hx +++ b/assets/data/discord.hx @@ -23,7 +23,7 @@ function onPlayStateUpdate() { } function onMenuLoaded(name:String) { - // Name is either "Main Menu", "Freeplay", "Title Screen", "Options Menu", "Credits Menu" + // Name is either "Main Menu", "Freeplay", "Title Screen", "Options Menu", "Credits Menu", "Beta Warning" DiscordUtil.changePresenceSince("In the Menus", null); } diff --git a/source/funkin/menus/BetaWarningState.hx b/source/funkin/menus/BetaWarningState.hx index 08d60f39..16201454 100644 --- a/source/funkin/menus/BetaWarningState.hx +++ b/source/funkin/menus/BetaWarningState.hx @@ -29,6 +29,8 @@ class BetaWarningState extends MusicBeatState { var off = Std.int((FlxG.height - (disclaimer.y + disclaimer.height)) / 2); disclaimer.y += off; titleAlphabet.y += off; + + DiscordUtil.call("onMenuLoaded", ["Beta Warning"]); } public override function update(elapsed:Float) { From 65ca3bdd0ff3e9f1efcfb07db036c4e9b311811d Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 15:52:39 +0100 Subject: [PATCH 17/21] Added updater screens to rpc --- assets/data/discord.hx | 2 +- source/funkin/backend/system/updating/UpdateAvailableScreen.hx | 2 ++ source/funkin/backend/system/updating/UpdateScreen.hx | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/assets/data/discord.hx b/assets/data/discord.hx index 205f88d6..9d5f0f6f 100644 --- a/assets/data/discord.hx +++ b/assets/data/discord.hx @@ -23,7 +23,7 @@ function onPlayStateUpdate() { } function onMenuLoaded(name:String) { - // Name is either "Main Menu", "Freeplay", "Title Screen", "Options Menu", "Credits Menu", "Beta Warning" + // Name is either "Main Menu", "Freeplay", "Title Screen", "Options Menu", "Credits Menu", "Beta Warning", "Update Available Screen", "Update Screen" DiscordUtil.changePresenceSince("In the Menus", null); } diff --git a/source/funkin/backend/system/updating/UpdateAvailableScreen.hx b/source/funkin/backend/system/updating/UpdateAvailableScreen.hx index 5b076058..d3a3869a 100644 --- a/source/funkin/backend/system/updating/UpdateAvailableScreen.hx +++ b/source/funkin/backend/system/updating/UpdateAvailableScreen.hx @@ -92,6 +92,8 @@ class UpdateAvailableScreen extends MusicBeatState { add(skipButton); oldPos = FlxG.mouse.getScreenPosition(); + + DiscordUtil.call("onMenuLoaded", ["Update Available Screen"]); } var destY:Float = 0; diff --git a/source/funkin/backend/system/updating/UpdateScreen.hx b/source/funkin/backend/system/updating/UpdateScreen.hx index 4fbe4cf8..323fda09 100644 --- a/source/funkin/backend/system/updating/UpdateScreen.hx +++ b/source/funkin/backend/system/updating/UpdateScreen.hx @@ -61,6 +61,8 @@ class UpdateScreen extends MusicBeatState { updater.execute(); FlxG.camera.addShader(rainbowShader = new CustomShader("engine/updaterShader")); + + DiscordUtil.call("onMenuLoaded", ["Update Screen"]); } From 7d17cc92fcbdef7c686d44ad58e27cceaa006157 Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 20:42:49 +0100 Subject: [PATCH 18/21] Improvement to changePresenceSince --- source/funkin/backend/utils/DiscordUtil.hx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index 783417e0..aa0e5657 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -148,16 +148,17 @@ class DiscordUtil #end } - public static function changePresenceSince(details:String, state:String, ?smallImageKey:String, ?offset:Float = 0) + public static function changePresenceSince(details:String, state:String, ?smallImageKey:String, ?time:Null = null) { #if DISCORD_RPC - var start:Float = Date.now().getTime() + offset; + if(time == null) + time = Date.now().getTime(); changePresenceAdvanced({ state: state, details: details, smallImageKey: smallImageKey, - startTimestamp: Std.int(start / 1000) + startTimestamp: Std.int(time / 1000) }); #end } From 3d00a61a5a5a5230d46a1af3d0cd37e2d416f91e Mon Sep 17 00:00:00 2001 From: NeeEoo Date: Sun, 24 Mar 2024 20:44:41 +0100 Subject: [PATCH 19/21] Im dumb --- source/funkin/backend/utils/DiscordUtil.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index aa0e5657..9df88b3e 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -148,7 +148,7 @@ class DiscordUtil #end } - public static function changePresenceSince(details:String, state:String, ?smallImageKey:String, ?time:Null = null) + public static function changePresenceSince(details:String, state:String, ?smallImageKey:String, ?time:Float) { #if DISCORD_RPC if(time == null) From 5eb0801c22637ca5adcbec23ffcb21dab05fa710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sun, 24 Mar 2024 21:00:12 +0100 Subject: [PATCH 20/21] optimized EVEN MORE the cne credits menu fully asynced and looks better :D --- commandline/commands/Update.hx | 4 +- source/funkin/backend/utils/HttpUtil.hx | 2 +- .../funkin/menus/credits/CreditsCodename.hx | 67 +++++++++++++++---- source/funkin/options/OptionsScreen.hx | 7 +- .../funkin/options/type/GithubIconOption.hx | 18 +++-- 5 files changed, 71 insertions(+), 27 deletions(-) diff --git a/commandline/commands/Update.hx b/commandline/commands/Update.hx index 92ae18c7..6ac0f0f3 100644 --- a/commandline/commands/Update.hx +++ b/commandline/commands/Update.hx @@ -75,10 +75,12 @@ class Update { // vswhere.exe its used to find any visual studio related installations on the system, including full visual studio ide installations, visual studio build tools installations, and other related components - Nex if (Compiler.getBuildTarget().toLowerCase() == "windows" && new Process('"C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe" -property catalog_productDisplayVersion').exitCode(true) == 1) { prettyPrint("Installing Microsoft Visual Studio Community (Dependency)"); + + // thanks to @crowplexus for these two lines! - Nex Sys.command("curl -# -O https://download.visualstudio.microsoft.com/download/pr/3105fcfe-e771-41d6-9a1c-fc971e7d03a7/8eb13958dc429a6e6f7e0d6704d43a55f18d02a253608351b6bf6723ffdaf24e/vs_Community.exe"); Sys.command("vs_Community.exe --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.Windows10SDK.19041 -p"); - FileSystem.deleteFile("vs_Community.exe"); + FileSystem.deleteFile("vs_Community.exe"); prettyPrint('If it didn\'t say it before: Because of this component if you want to compile you have to restart the device.'); Sys.print("Do you wish to do it now [y/n]? "); if(Sys.stdin().readLine().toLowerCase() == "y") Sys.command("shutdown /r /t 0 /f"); diff --git a/source/funkin/backend/utils/HttpUtil.hx b/source/funkin/backend/utils/HttpUtil.hx index 1edbbfd2..f2d3caf8 100644 --- a/source/funkin/backend/utils/HttpUtil.hx +++ b/source/funkin/backend/utils/HttpUtil.hx @@ -63,7 +63,7 @@ class HttpUtil { // 301: Moved Permanently, 302: Found (Moved Temporarily), 307: Temporary Redirect, 308: Permanent Redirect - Nex case 301 | 302 | 307 | 308: - trace("Redirected with status code: " + status); + Logs.traceColored([Logs.logText('[Connection Status] ', BLUE), Logs.logText('Redirected with status code: ', YELLOW), Logs.logText('$status', GREEN)], WARNING); return true; } return false; diff --git a/source/funkin/menus/credits/CreditsCodename.hx b/source/funkin/menus/credits/CreditsCodename.hx index 2a9dd42b..579360ed 100644 --- a/source/funkin/menus/credits/CreditsCodename.hx +++ b/source/funkin/menus/credits/CreditsCodename.hx @@ -1,5 +1,7 @@ package funkin.menus.credits; +import funkin.options.PlayerSettings; +import flixel.util.FlxColor; import funkin.backend.system.github.GitHub; import funkin.options.type.GithubIconOption; import flixel.text.FlxText; @@ -9,44 +11,74 @@ using StringTools; class CreditsCodename extends funkin.options.OptionsScreen { public var error:Bool = false; public var author:String = "FNF-CNE-Devs"; + public var mainDevCol:FlxColor = 0xFF9C35D5; + public var minContrCol:FlxColor = 0xFFB4A7DA; + public var totalContributions:Int = 0; public override function new() { super("Codename Engine", "All the contributors of the engine! - Press RESET to update the list (One reset per 2 minutes)."); - checkUpdate(); - displayList(); + tryUpdating(true); } + // blame the secondary threads if the code has to look this bad - Nex + private var _canReset:Bool = true; + private var _downloadingSteps:Int = 0; public override function update(elapsed:Float) { - if (funkin.options.PlayerSettings.solo.controls.RESET && checkUpdate()) { + super.update(elapsed); + + if (_downloadingSteps == 2) { + _downloadingSteps = 0; + _canReset = true; displayList(); + } else if (_downloadingSteps == 1) { + _downloadingSteps = 0; + _canReset = true; updateMenuDesc(); } - super.update(elapsed); + else if(_canReset && PlayerSettings.solo.controls.RESET) tryUpdating(); + } + + public function tryUpdating(forceDisplaying:Bool = false) { + updateMenuDesc("Downloading List..."); + _canReset = false; + Main.execAsync(function() { + if(checkUpdate() || forceDisplaying) _downloadingSteps = 2; + else _downloadingSteps = 1; + }); } public override function updateMenuDesc(?txt:String) { + if(!_canReset) return; super.updateMenuDesc(txt); - parent.treeParent.pathDesc.applyMarkup(parent.treeParent.pathDesc.text, [new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF9C35D5), "*")]); + updateMarkup(); + } + + public function updateMarkup() { + if(parent == null || parent.treeParent == null) return; + var text:String = parent.treeParent.pathDesc.text; + parent.treeParent.pathDesc.text = ""; + parent.treeParent.pathDesc.applyMarkup(text, [ + new FlxTextFormatMarkerPair(new FlxTextFormat(mainDevCol), '*'), + new FlxTextFormatMarkerPair(new FlxTextFormat(FlxColor.interpolate(minContrCol, mainDevCol, Options.contributors[curSelected].contributions / totalContributions)), '~') + ]); } public function checkUpdate():Bool { var curTime:Float = Date.now().getTime(); - if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits + if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits - Nex Options.lastUpdated = curTime; error = false; - //Main.execAsync(function() { var idk = GitHub.getContributors(author, "CodenameEngine", function(e) { error = true; var errMsg:String = 'Error while trying to download contributors list:\n${CoolUtil.removeIP(e.message)}'; Logs.traceColored([Logs.logText(errMsg.replace('\n', ' '), RED)], ERROR); funkin.backend.utils.NativeAPI.showMessageBox("Codename Engine Warning", errMsg, MSG_WARNING); }); - //}); if(error) return false; Options.contributors = idk; - trace('List Updated!'); + trace('Contributors list Updated!'); var errorOnMain:Bool = false; var idk2 = GitHub.getOrganizationMembers(author, function(e) { @@ -55,7 +87,10 @@ class CreditsCodename extends funkin.options.OptionsScreen { Logs.traceColored([Logs.logText(errMsg.replace('\n', ' '), RED)], ERROR); funkin.backend.utils.NativeAPI.showMessageBox("Codename Engine Warning", errMsg, MSG_WARNING); }); - if(!errorOnMain) Options.mainDevs = [for(m in idk2) m.id]; + if(!errorOnMain) { + Options.mainDevs = [for(m in idk2) m.id]; + trace('Main Devs list Updated!'); + } return true; } @@ -70,13 +105,17 @@ class CreditsCodename extends funkin.options.OptionsScreen { remove(members[0], true); } - var totalContributions = 0; + totalContributions = 0; for(c in Options.contributors) totalContributions += c.contributions; for(c in Options.contributors) { - var desc:String = 'Total Contributions: ${c.contributions} / ${totalContributions} (${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%) - Select to open GitHub account'; - if(Options.mainDevs.contains(c.id)) desc += " *- Public member of the main Devs!*"; - var opt:GithubIconOption = new GithubIconOption(c, desc); + var opt:GithubIconOption = new GithubIconOption(c, 'Total Contributions: ~${c.contributions}~ / *${totalContributions}* (~${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%~) - Select to open GitHub account'); + if(Options.mainDevs.contains(c.id)) { + opt.desc += " *- Public member of the main Devs!*"; + @:privateAccess opt.__text.color = mainDevCol; + } add(opt); } + + updateMenuDesc(); } } \ No newline at end of file diff --git a/source/funkin/options/OptionsScreen.hx b/source/funkin/options/OptionsScreen.hx index f21bdaaf..45580821 100644 --- a/source/funkin/options/OptionsScreen.hx +++ b/source/funkin/options/OptionsScreen.hx @@ -70,11 +70,8 @@ class OptionsScreen extends FlxTypedSpriteGroup { } public function updateMenuDesc(?customTxt:String) { - if (parent.treeParent == null) return; - - var text:String = members[curSelected].desc; - if (customTxt != null) text = customTxt; - parent.treeParent.updateDesc(text); + if (parent == null || parent.treeParent == null) return; + parent.treeParent.updateDesc(customTxt != null ? customTxt : members[curSelected].desc); } public dynamic function onClose(o:OptionsScreen) {} diff --git a/source/funkin/options/type/GithubIconOption.hx b/source/funkin/options/type/GithubIconOption.hx index 7f41b8d4..5c780165 100644 --- a/source/funkin/options/type/GithubIconOption.hx +++ b/source/funkin/options/type/GithubIconOption.hx @@ -19,10 +19,10 @@ class GithubIconOption extends TextOption return usePortrait = value; } - public function new(user:Dynamic, desc:String, ?callback:Void->Void, ?customName:String, size:Int = 96, usePortrait:Bool = true) { + public function new(user:Dynamic, desc:String, ?callback:Void->Void, ?customName:String, size:Int = 96, usePortrait:Bool = true, waitUntilLoad:Float = 0.25) { super(customName == null ? user.login : customName, desc, callback == null ? function() CoolUtil.openURL(user.html_url) : callback); this.user = user; - this.icon = new GithubUserIcon(user, size); + this.icon = new GithubUserIcon(user, size, waitUntilLoad); this.usePortrait = usePortrait; add(icon); } @@ -30,22 +30,28 @@ class GithubIconOption extends TextOption class GithubUserIcon extends FlxSprite { - private var loading:Bool = false; + public var waitUntilLoad:Null; private var user:Dynamic; private var size:Int; - public override function new(user:Dynamic, size:Int = 96) { + public override function new(user:Dynamic, size:Int = 96, waitUntilLoad:Float = 0.25) { this.user = user; this.size = size; + this.waitUntilLoad = waitUntilLoad; super(); makeGraphic(size, size, FlxColor.TRANSPARENT); antialiasing = true; } + override function update(elapsed:Float) { + if(waitUntilLoad > 0) waitUntilLoad -= elapsed; + super.update(elapsed); + } + final mutex = new sys.thread.Mutex(); override function drawComplex(camera:FlxCamera):Void { // Making the image downlaod only if the player actually sees it on the screeeeen - Nex - if(!loading) { - loading = true; + if(waitUntilLoad <= 0) { + waitUntilLoad = null; Main.execAsync(function() { var key:String = 'GITHUB-USER:${user.login}'; var bmap:Dynamic = FlxG.bitmap.get(key); From a0482e0dcde0f5872b21cc10606994448380f2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sun, 24 Mar 2024 21:16:23 +0100 Subject: [PATCH 21/21] kill me --- libs.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs.xml b/libs.xml index 7a82fd43..6463128d 100644 --- a/libs.xml +++ b/libs.xml @@ -16,8 +16,8 @@ - + - \ No newline at end of file +