hxdiscord_rpc, away3D fork and much more
5H FOR COMPILING. 5 FUCKING HOURS FOR MACRO ERRORS. Co-Authored-By: Ne_Eo <NeeEoo@users.noreply.github.com>
This commit is contained in:
@@ -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)
|
||||
</details>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -10,12 +10,12 @@
|
||||
|
||||
<!-- Other Libraries -->
|
||||
<git name="hscript-improved" url="https://github.com/FNF-CNE-Devs/hscript-improved" ref="custom-classes" />
|
||||
<git name="discord-rpc" url="https://github.com/Aidan63/linc_discord-rpc" />
|
||||
<git name="flxanimate" url="https://github.com/FNF-CNE-Devs/flxanimate" />
|
||||
<lib name="hxdiscord_rpc" />
|
||||
<lib name="hxvlc" />
|
||||
|
||||
<!-- Documentation and other features -->
|
||||
<lib name="away3d" />
|
||||
<lib name="away3d" url="https://github.com/FNF-CNE-Devs/away3d" />
|
||||
<!-- <lib name="dox" /> -->
|
||||
<lib name="format" />
|
||||
<lib name="markdown" />
|
||||
|
||||
+2
-1
@@ -170,10 +170,11 @@
|
||||
<haxelib name="flxanimate" />
|
||||
|
||||
<haxelib name="hscript-improved" />
|
||||
<haxelib name="discord-rpc" if="DISCORD_RPC"/>
|
||||
<haxelib name="hxdiscord_rpc" if="DISCORD_RPC"/>
|
||||
<haxelib name="markdown" />
|
||||
|
||||
<haxedef name="no-deprecation-warnings"/>
|
||||
<haxedef name="DISCORD_DISABLE_IO_THREAD" if="DISCORD_RPC"/>
|
||||
|
||||
<!-- _________________________________ Additional stuff _______________________________ -->
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<GitHubRelease> {
|
||||
#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<GitHubContributor> {
|
||||
#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<GitHubContributor> {
|
||||
#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<GitHubRelease>, 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)";
|
||||
|
||||
@@ -37,4 +37,21 @@ class Utils {
|
||||
return expr;
|
||||
#end
|
||||
}
|
||||
|
||||
public static macro function safeSet(variable:Null<Expr>, value:Null<Expr>):Null<Expr> {
|
||||
#if macro
|
||||
return macro if (${value} != null) ${variable} = ${value};
|
||||
#end
|
||||
}
|
||||
public static macro function safeSetWrapper(variable:Null<Expr>, value:Null<Expr>, wrapper:Null<Expr>):Null<Expr> {
|
||||
#if macro
|
||||
return macro if (${value} != null) ${variable} = ${wrapper}(${value});
|
||||
#end
|
||||
}
|
||||
|
||||
public static macro function safeReflection(variable:Null<Expr>, value:Null<Expr>, field:Null<Expr>):Null<Expr> {
|
||||
#if macro
|
||||
return macro if (Reflect.hasField(${value}, ${field})) ${variable} = Reflect.field(${value}, ${field});
|
||||
#end
|
||||
}
|
||||
}
|
||||
@@ -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<DiscordUser>):Void
|
||||
{
|
||||
var requestPtr:cpp.Star<DiscordUser> = 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;
|
||||
}
|
||||
}
|
||||
|
||||
@: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<DiscordUser>)
|
||||
{
|
||||
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<Int, haxe.Int64>;
|
||||
var ?endTimestamp:OneOfTwo<Int, haxe.Int64>;
|
||||
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<Int, cpp.Int8>;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -106,6 +106,7 @@ class NoteGroup extends FlxTypedGroup<Note> {
|
||||
if (members == null)
|
||||
return null;
|
||||
|
||||
// TODO: maybe lastIndexOf
|
||||
var index:Int = members.indexOfFromLast(Object);
|
||||
|
||||
if (index < 0)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user