Skip to content

Commit

Permalink
Asynced credits and more (#223)
Browse files Browse the repository at this point in the history
* let me cook

* shut up

* offline part but cached bitmaps wont work raaaaaah

* bitch it works

* github node in credits.xml and more

have to finish the no api method

* non api method working

im baaack, ive been kinda busy these days

* balls

* done ig

* non api method first

* less tries

* forgor to update the non github part
  • Loading branch information
NexIsDumb authored Feb 4, 2024
1 parent 38ea98c commit a71a02e
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 52 deletions.
2 changes: 2 additions & 0 deletions assets/data/config/credits.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<!DOCTYPE codename-mod-credits>
<!-- TEMPLATE FOR CUSTOM CREDITS!!! -->
<menu name="Mod Credits" desc="Modify mod credits here">
<!-- \/ You can also set the portrait shader as false as you can see below in the github one -->
<credit name="Credit Example" desc="Click me to know more about me!" icon="credit icon example" size="130" url="https://youtu.be/fugtxz1znVw"/>
<github user="NexIsDumb" customName="Nex is Dumb" desc="The bitch who made these credits menus" size="100" portrait="false"/>
</menu>
86 changes: 80 additions & 6 deletions source/funkin/backend/system/github/GitHub.hx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import haxe.Http;
class GitHub {
/**
* Gets all the releases from a specific GitHub repository using the GitHub API.
* @param user
* @param repository
* @param user The user/group that owns the repository
* @param repository The repository name
* @return Releases
*/
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
Expand All @@ -29,6 +29,12 @@ class GitHub {
return [];
}

/**
* Gets the contributors list from a specific GitHub repository using the GitHub API.
* @param user The user/group that owns the repository
* @param repository The repository name
* @return Contributors List
*/
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
try {
var url = 'https://api.github.com/repos/${user}/${repository}/contributors';
Expand All @@ -45,6 +51,27 @@ class GitHub {
return [];
}

/**
* Gets a specific GitHub user/group using the GitHub API.
* @param user The user/group to get
* @return User/Group
*/
public static function getUser(user:String, ?onError:Exception->Void):GitHubUser {
try {
var url = 'https://api.github.com/users/$user';

var data = Json.parse(__requestOnGitHubServers(url));
if (Reflect.hasField(data, "documentation_url"))
throw __parseGitHubException(data);

return data;
} catch(e) {
if (onError != null)
onError(e);
}
return null;
}

/**
* Filters all releases gotten by `getReleases`
* @param releases Releases
Expand All @@ -58,29 +85,52 @@ class GitHub {
public static function __requestOnGitHubServers(url:String) {
var h = new Http(url);
h.setHeader("User-Agent", "request");

var r = null;
h.onStatus = function(s) {
if(isRedirect(s))
r = __requestOnGitHubServers(h.responseHeaders.get("Location"));
};

h.onData = function(d) {
r = d;
if(r == null) r = d;
}
h.onError = function(e) {
throw e;
}

h.request(false);
return r;
}
public static function __requestBytesOnGitHubServers(url:String) {
var h = new Http(url);
h.setHeader("User-Agent", "request");

var r = null;
h.onStatus = function(s) {
if(isRedirect(s))
r = __requestBytesOnGitHubServers(h.responseHeaders.get("Location"));
};

h.onBytes = function(d) {
r = 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_isDumb
case 301 | 302 | 307 | 308 :
trace("Redirected with status code: " + status);
return true;
}
return false;
}
private static function __parseGitHubException(obj:Dynamic):GitHubException {
var msg:String = "(No message)";
var url:String = "(No API url)";
Expand All @@ -99,18 +149,33 @@ import haxe.Exception;
class GitHub {
/**
* Gets all the releases from a specific GitHub repository using the GitHub API.
* @param user
* @param repository
* @param user The user/group that owns the repository
* @param repository The repository name
* @return Releases
*/
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
return [];
}

/**
* Gets the contributors list from a specific GitHub repository using the GitHub API.
* @param user The user/group that owns the repository
* @param repository The repository name
* @return Contributors List
*/
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
return [];
}

/**
* Gets a specific GitHub user/group using the GitHub API.
* @param user The user/group to get
* @return User/Group
*/
public static function getUser(user:String, ?onError:Exception->Void):GitHubUser {
return null;
}

/**
* Filters all releases gotten by `getReleases`
* @param releases Releases
Expand All @@ -130,5 +195,14 @@ class GitHub {
private static function __parseGitHubException(obj:Dynamic):GitHubException {
return null;
}
private static function isRedirect(status:Int):Bool {
switch (status) {
// 301: Moved Permanently, 302: Found (Moved Temporarily), 307: Temporary Redirect, 308: Permanent Redirect - Nex_isDumb
case 301 | 302 | 307 | 308 :
trace("Redirected with status code: " + status);
return true;
}
return false;
}
}
#end
11 changes: 10 additions & 1 deletion source/funkin/backend/utils/CoolUtil.hx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class CoolUtil

/**
* Returns a string representation of a size, following this format: `1.02 GB`, `134.00 MB`
* @param size Size to convert ot string
* @param size Size to convert to string
* @return String Result string representation
*/
public static function getSizeString(size:Float):String {
Expand All @@ -149,6 +149,15 @@ class CoolUtil
return '${Std.int(rSize) + "." + addZeros(Std.string(Std.int((rSize % 1) * 100)), 2)}${labels[label]}';
}

/**
* Replaces in a string any kind of IP with `[Your IP]` making the string safer to trace.
* @param msg String to check and edit
* @return String Result without any kind of IP
*/
public static inline function removeIP(msg:String):String {
return ~/\d+.\d+.\d+.\d+/.replace(msg, "[Your IP]"); // For now its just IPs but who knows in the future.. - Nex_isDumb
}

/**
* Alternative linear interpolation function for each frame use, without worrying about framerate changes.
* @param v1 Begin value
Expand Down
4 changes: 3 additions & 1 deletion source/funkin/game/StrumLine.hx
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,9 @@ class StrumLine extends FlxTypedGroup<Strum> {
if(data.scrollSpeed != null)
babyArrow.scrollSpeed = data.scrollSpeed;

var event = PlayState.instance.scripts.event("onStrumCreation", EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix));
var event = EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix);
event.__doAnimation = !MusicBeatState.skipTransIn;
event = PlayState.instance.scripts.event("onStrumCreation", event);

if (!event.cancelled) {
babyArrow.frames = Paths.getFrames(event.sprite);
Expand Down
1 change: 1 addition & 0 deletions source/funkin/menus/StoryMenuState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class StoryMenuState extends MusicBeatState {
arrow.animation.addByPrefix('idle', 'arrow $dir');
arrow.animation.addByPrefix('press', 'arrow push $dir', 24, false);
arrow.animation.play('idle');
arrow.antialiasing = true;
add(arrow);
}
rightArrow.x -= rightArrow.width;
Expand Down
20 changes: 9 additions & 11 deletions source/funkin/menus/credits/CreditsCodename.hx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package funkin.menus.credits;

import funkin.backend.system.github.GitHub;
import funkin.options.type.PortraitOption;
import funkin.options.type.GithubIconOption;

using StringTools;

class CreditsCodename extends funkin.options.OptionsScreen {
public var error:Bool = false;

public override function new()
{
super("Codename Engine", "All the contributors of the engine! - Press RESET to update the list (One reset per 2 minutes).");
Expand All @@ -21,7 +23,6 @@ class CreditsCodename extends funkin.options.OptionsScreen {
super.update(elapsed);
}

var error:Bool = false;
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 - Nex_isDumb
Expand All @@ -31,15 +32,14 @@ class CreditsCodename extends funkin.options.OptionsScreen {
//Main.execAsync(function() {
var idk = GitHub.getContributors("FNF-CNE-Devs", "CodenameEngine", function(e) {
error = true;
var errMsg:String = ~/\d+.\d+.\d+.\d+/.replace(e.message, "[Your IP]"); // Removing sensitive stuff - Nex_isDumb
errMsg = 'Error while trying to download contributors list:\n$errMsg';
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!');
return true;
Expand All @@ -49,7 +49,7 @@ class CreditsCodename extends funkin.options.OptionsScreen {
//if (curSelected > Options.contributors.length - 1) changeSelection(-(curSelected - (Options.contributors.length - 1)));
if (curSelected > Options.contributors.length - 1) curSelected = Options.contributors.length - 1;
changeSelection(0, true);

while (members.length > 0) {
members[0].destroy();
remove(members[0], true);
Expand All @@ -58,12 +58,10 @@ class CreditsCodename extends funkin.options.OptionsScreen {
var totalContributions = 0;
for(c in Options.contributors) totalContributions += c.contributions;
for(c in Options.contributors) {
var opt:PortraitOption = new PortraitOption(
c.login,
'Total Contributions: ${c.contributions} / ${totalContributions} (${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%) - Select to open GitHub account',
function() CoolUtil.openURL(c.html_url)
var opt:GithubIconOption = new GithubIconOption(
c,
'Total Contributions: ${c.contributions} / ${totalContributions} (${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%) - Select to open GitHub account'
);
if(!error) opt.loadFromGithub(c);
add(opt);
}
}
Expand Down
54 changes: 38 additions & 16 deletions source/funkin/menus/credits/CreditsMain.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package funkin.menus.credits;

import funkin.backend.system.github.GitHub;
import funkin.options.OptionsScreen;
import funkin.options.type.*;
import funkin.options.TreeMenu;
Expand Down Expand Up @@ -27,7 +28,7 @@ class CreditsMain extends TreeMenu {
} catch(e) {
Logs.trace('Error while parsing credits.xml: ${Std.string(e)}', ERROR);
}

if (access != null)
for(c in parseCreditsFromXML(access, source))
selectables.push(c);
Expand All @@ -51,24 +52,45 @@ class CreditsMain extends TreeMenu {
var credsMenus:Array<OptionType> = [];

for(node in xml.elements) {
if (!node.has.name) {
Logs.trace("A credit node requires a name attribute.", WARNING);
continue;
}
var name = node.getAtt("name");
var desc = node.getAtt("desc").getDefault("No Description");

switch(node.name) {
case "credit":
credsMenus.push(new PortraitOption(name, desc, function() if(node.has.url) CoolUtil.openURL(node.att.url),
node.has.icon && Paths.assetsTree.existsSpecific(Paths.image('credits/${node.att.icon}'), "IMAGE", source) ?
FlxG.bitmap.add(Paths.image('credits/${node.att.icon}')) : null, node.has.size ? Std.parseInt(node.att.size) : 96
));
if (node.name == "github") {
if (!node.has.user) {
Logs.trace("A github node requires a user attribute.", WARNING);
continue;
}

var username = node.getAtt("user");
var user = { // Kind of forcing - Nex_isDumb
login: username,
html_url: 'https://github.com/$username',
avatar_url: 'https://github.com/$username.png'
};

case "menu":
credsMenus.push(new TextOption(name + " >", desc, function() {
optionsTree.add(new OptionsScreen(name, desc, parseCreditsFromXML(node, source)));
}));
credsMenus.push(new GithubIconOption(user, desc, null,
node.has.customName ? node.att.customName : null, node.has.size ? Std.parseInt(node.att.size) : 96,
node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true
));
} else {
if (!node.has.name) {
Logs.trace("A credit node requires a name attribute.", WARNING);
continue;
}
var name = node.getAtt("name");

switch(node.name) {
case "credit":
credsMenus.push(new PortraitOption(name, desc, function() if(node.has.url) CoolUtil.openURL(node.att.url),
node.has.icon && Paths.assetsTree.existsSpecific(Paths.image('credits/${node.att.icon}'), "IMAGE", source) ?
FlxG.bitmap.add(Paths.image('credits/${node.att.icon}')) : null, node.has.size ? Std.parseInt(node.att.size) : 96,
node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true
));

case "menu":
credsMenus.push(new TextOption(name + " >", desc, function() {
optionsTree.add(new OptionsScreen(name, desc, parseCreditsFromXML(node, source)));
}));
}
}
}

Expand Down
Loading

0 comments on commit a71a02e

Please sign in to comment.