Cleaned up some code

This commit is contained in:
NeeEoo
2023-03-20 20:34:50 +01:00
parent 7c091445c2
commit c95c1e2975
28 changed files with 1390 additions and 1361 deletions
+58 -58
View File
@@ -4,66 +4,66 @@ import openfl.display.BitmapData;
import flixel.util.FlxColor;
class BitmapUtil {
/**
* Returns the most present color in a Bitmap.
* @param bmap Bitmap
* @return FlxColor Color that is the most present.
*/
public static function getMostPresentColor(bmap:BitmapData):FlxColor {
// map containing all the colors and the number of times they've been assigned.
var colorMap:Map<FlxColor, Float> = [];
var color:FlxColor = 0;
var fixedColor:FlxColor = 0;
/**
* Returns the most present color in a Bitmap.
* @param bmap Bitmap
* @return FlxColor Color that is the most present.
*/
public static function getMostPresentColor(bmap:BitmapData):FlxColor {
// map containing all the colors and the number of times they've been assigned.
var colorMap:Map<FlxColor, Float> = [];
var color:FlxColor = 0;
var fixedColor:FlxColor = 0;
for(y in 0...bmap.height) {
for(x in 0...bmap.width) {
color = bmap.getPixel32(x, y);
fixedColor = 0xFF000000 + (color % 0x1000000);
if (colorMap[fixedColor] == null)
colorMap[fixedColor] = 0;
colorMap[fixedColor] += color.alphaFloat;
}
}
for(y in 0...bmap.height) {
for(x in 0...bmap.width) {
color = bmap.getPixel32(x, y);
fixedColor = 0xFF000000 + (color % 0x1000000);
if (colorMap[fixedColor] == null)
colorMap[fixedColor] = 0;
colorMap[fixedColor] += color.alphaFloat;
}
}
var mostPresentColor:FlxColor = 0;
var mostPresentColorCount:Float = -1;
for(c=>n in colorMap) {
if (n > mostPresentColorCount) {
mostPresentColorCount = n;
mostPresentColor = c;
}
}
return mostPresentColor;
}
/**
* Returns the most present saturated color in a Bitmap.
* @param bmap Bitmap
* @return FlxColor Color that is the most present.
*/
public static function getMostPresentSaturatedColor(bmap:BitmapData):FlxColor {
// map containing all the colors and the number of times they've been assigned.
var colorMap:Map<FlxColor, Float> = [];
var color:FlxColor = 0;
var fixedColor:FlxColor = 0;
var mostPresentColor:FlxColor = 0;
var mostPresentColorCount:Float = -1;
for(c=>n in colorMap) {
if (n > mostPresentColorCount) {
mostPresentColorCount = n;
mostPresentColor = c;
}
}
return mostPresentColor;
}
/**
* Returns the most present saturated color in a Bitmap.
* @param bmap Bitmap
* @return FlxColor Color that is the most present.
*/
public static function getMostPresentSaturatedColor(bmap:BitmapData):FlxColor {
// map containing all the colors and the number of times they've been assigned.
var colorMap:Map<FlxColor, Float> = [];
var color:FlxColor = 0;
var fixedColor:FlxColor = 0;
for(y in 0...bmap.height) {
for(x in 0...bmap.width) {
color = bmap.getPixel32(x, y);
fixedColor = 0xFF000000 + (color % 0x1000000);
if (colorMap[fixedColor] == null)
colorMap[fixedColor] = 0;
colorMap[fixedColor] += color.alphaFloat * 0.33 + (0.67 * (color.saturation * (2 * (color.lightness > 0.5 ? 0.5 - (color.lightness) : color.lightness))));
}
}
for(y in 0...bmap.height) {
for(x in 0...bmap.width) {
color = bmap.getPixel32(x, y);
fixedColor = 0xFF000000 + (color % 0x1000000);
if (colorMap[fixedColor] == null)
colorMap[fixedColor] = 0;
colorMap[fixedColor] += color.alphaFloat * 0.33 + (0.67 * (color.saturation * (2 * (color.lightness > 0.5 ? 0.5 - (color.lightness) : color.lightness))));
}
}
var mostPresentColor:FlxColor = 0;
var mostPresentColorCount:Float = -1;
for(c=>n in colorMap) {
if (n > mostPresentColorCount) {
mostPresentColorCount = n;
mostPresentColor = c;
}
}
return mostPresentColor;
}
var mostPresentColor:FlxColor = 0;
var mostPresentColorCount:Float = -1;
for(c=>n in colorMap) {
if (n > mostPresentColorCount) {
mostPresentColorCount = n;
mostPresentColor = c;
}
}
return mostPresentColor;
}
}
+111 -111
View File
@@ -11,142 +11,142 @@ import lime.app.Application;
#end
class DiscordUtil {
public static var currentID: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 var currentID: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() {
#if DISCORD_RPC
reloadJsonData();
discordThread = Thread.create(function() {
while (true)
{
while(!ready) {
Sys.sleep(1/60);
}
trace("Processing Discord RPC...");
DiscordRpc.process();
Sys.sleep(2);
}
});
public static function init() {
#if DISCORD_RPC
reloadJsonData();
discordThread = Thread.create(function() {
while (true)
{
while(!ready) {
Sys.sleep(1/60);
}
trace("Processing Discord RPC...");
DiscordRpc.process();
Sys.sleep(2);
}
});
Application.current.onExit.add(function(exitCode) {
shutdown();
});
#end
}
#end
}
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) {
Logs.trace('Couldn\'t load Discord RPC configuration: ${e.toString()}', ERROR);
}
}
trace(data);
data.setFieldDefault("clientID", "1027994136193810442");
data.setFieldDefault("logoKey", "icon");
data.setFieldDefault("logoText", Application.current.meta.get('title'));
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) {
Logs.trace('Couldn\'t load Discord RPC configuration: ${e.toString()}', ERROR);
}
}
trace(data);
data.setFieldDefault("clientID", "1027994136193810442");
data.setFieldDefault("logoKey", "icon");
data.setFieldDefault("logoText", Application.current.meta.get('title'));
changeClientID(data.clientID);
#end
}
changeClientID(data.clientID);
#end
}
public static function changePresence(details:String, state:String, ?smallImageKey : String) {
#if DISCORD_RPC
changePresenceAdvanced({
state: state,
details: details,
smallImageKey: smallImageKey
});
#end
}
public static function changePresence(details:String, state:String, ?smallImageKey : String) {
#if DISCORD_RPC
changePresenceAdvanced({
state: state,
details: details,
smallImageKey: smallImageKey
});
#end
}
public static function changeSongPresence(details:String, state:String, audio:FlxSound, ?smallImageKey : String) {
#if DISCORD_RPC
var start:Float = 0;
var end:Float = 0;
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) {
start = Date.now().getTime();
end = start + (audio.length - audio.time);
}
if (audio != null && audio.playing) {
start = Date.now().getTime();
end = start + (audio.length - audio.time);
}
changePresenceAdvanced({
state: state,
details: details,
smallImageKey: smallImageKey,
startTimestamp: Std.int(start / 1000),
endTimestamp: Std.int(end / 1000)
});
#end
}
changePresenceAdvanced({
state: state,
details: details,
smallImageKey: smallImageKey,
startTimestamp: Std.int(start / 1000),
endTimestamp: Std.int(end / 1000)
});
#end
}
public static function changePresenceAdvanced(data:#if DISCORD_RPC DiscordPresenceOptions #else Dynamic #end) {
#if DISCORD_RPC
if (data == null) return;
public static function changePresenceAdvanced(data:#if DISCORD_RPC DiscordPresenceOptions #else Dynamic #end) {
#if DISCORD_RPC
if (data == null) return;
if (data.largeImageKey == null)
data.largeImageKey = DiscordUtil.data.logoKey;
if (data.largeImageText == null)
data.largeImageText = DiscordUtil.data.logoText;
#if GLOBAL_SCRIPT
var event = funkin.scripting.GlobalScript.event("onDiscordPresenceUpdate", EventManager.get(DiscordPresenceUpdateEvent).recycle(data));
if (event.cancelled) return;
#end
DiscordRpc.presence(data);
#end
}
public static function changeClientID(id:String) {
#if DISCORD_RPC
if (currentID != null) {
DiscordRpc.shutdown();
}
if (data.largeImageKey == null)
data.largeImageKey = DiscordUtil.data.logoKey;
if (data.largeImageText == null)
data.largeImageText = DiscordUtil.data.logoText;
ready = false;
#if GLOBAL_SCRIPT
var event = funkin.scripting.GlobalScript.event("onDiscordPresenceUpdate", EventManager.get(DiscordPresenceUpdateEvent).recycle(data));
if (event.cancelled) return;
DiscordRpc.start({
#end
DiscordRpc.presence(data);
#end
}
public static function changeClientID(id:String) {
#if DISCORD_RPC
if (currentID != null) {
DiscordRpc.shutdown();
}
ready = false;
DiscordRpc.start({
clientID: id,
onReady: function() {
Logs.trace('Discord RPC started');
ready = true;
},
Logs.trace('Discord RPC started');
ready = true;
},
onError: onError,
onDisconnected: onDisconnected
});
currentID = id;
currentID = id;
#end
}
#end
}
public static function shutdown() {
#if DISCORD_RPC
DiscordRpc.shutdown();
#end
}
public static function shutdown() {
#if DISCORD_RPC
DiscordRpc.shutdown();
#end
}
// HANDLERS
#if DISCORD_RPC
static function onError(_code:Int, _message:String) {
Logs.trace('Discord RPC Error: ${_message} (Code: $_code)', ERROR);
}
// HANDLERS
#if DISCORD_RPC
static function onError(_code:Int, _message:String) {
Logs.trace('Discord RPC Error: ${_message} (Code: $_code)', ERROR);
}
static function onDisconnected(_code:Int, _message:String) {
Logs.trace('Discord RPC Disconnected: ${_message} (Code: $_code)', WARNING);
}
#end
static function onDisconnected(_code:Int, _message:String) {
Logs.trace('Discord RPC Disconnected: ${_message} (Code: $_code)', WARNING);
}
#end
}
typedef DiscordJson = {
var ?clientID:String;
var ?logoKey:String;
var ?logoText:String;
var ?clientID:String;
var ?logoKey:String;
var ?logoText:String;
}
+8 -8
View File
@@ -4,12 +4,12 @@ import funkin.scripting.Script;
import funkin.scripting.MultiThreadedScript;
class EngineUtil {
/**
* Starts a new multithreaded script.
* This script will share all the variables with the current one, which means already existing callbacks will be replaced by new ones on conflict.
* @param path
*/
public static function startMultithreadedScript(path:String) {
return new MultiThreadedScript(path, Script.curScript);
}
/**
* Starts a new multithreaded script.
* This script will share all the variables with the current one, which means already existing callbacks will be replaced by new ones on conflict.
* @param path
*/
public static function startMultithreadedScript(path:String) {
return new MultiThreadedScript(path, Script.curScript);
}
}
+24 -24
View File
@@ -7,37 +7,37 @@ import flixel.util.FlxColor;
* Gets rid of precision issues with `FlxColor.interpolate`
*/
class FlxInterpolateColor {
public var red:Float = 0;
public var green:Float = 0;
public var blue:Float = 0;
public var alpha:Float = 0;
public var red:Float = 0;
public var green:Float = 0;
public var blue:Float = 0;
public var alpha:Float = 0;
public var color(get, set):FlxColor;
public var color(get, set):FlxColor;
private inline function get_color()
return FlxColor.fromRGBFloat(red, green, blue, alpha);
private inline function get_color()
return FlxColor.fromRGBFloat(red, green, blue, alpha);
private inline function set_color(c:FlxColor):FlxColor {
red = c.redFloat;
green = c.greenFloat;
blue = c.blueFloat;
alpha = c.alphaFloat;
return c;
}
private inline function set_color(c:FlxColor):FlxColor {
red = c.redFloat;
green = c.greenFloat;
blue = c.blueFloat;
alpha = c.alphaFloat;
return c;
}
public inline function toString()
return '[FlxInterpolateColor - (R:${red} | G:${green} | B:${blue} | A:${alpha})]';
public function new(color:FlxColor) {
this.color = color;
}
public inline function toString()
return '[FlxInterpolateColor - (R:${red} | G:${green} | B:${blue} | A:${alpha})]';
public function new(color:FlxColor) {
this.color = color;
}
public function lerpTo(color:FlxColor, ratio:Float) {
red = (color.redFloat - red) * ratio + red;
public function lerpTo(color:FlxColor, ratio:Float) {
red = (color.redFloat - red) * ratio + red;
green = (color.greenFloat - green) * ratio + green;
blue = (color.blueFloat - blue) * ratio + blue;
alpha = (color.alphaFloat - alpha) * ratio + alpha;
}
}
public inline function fpsLerpTo(color:FlxColor, ratio:Float)
lerpTo(color, ratio * 60 * FlxG.elapsed);
public inline function fpsLerpTo(color:FlxColor, ratio:Float)
lerpTo(color, ratio * 60 * FlxG.elapsed);
}
+27 -27
View File
@@ -5,36 +5,36 @@ package funkin.utils;
* DOESNT SUPPORT CATEGORIES YET!!
*/
class IniUtil {
public static inline function parseAsset(assetPath:String, ?defaultVariables:Map<String, String>)
return parseString(Assets.getText(assetPath), defaultVariables);
public static inline function parseAsset(assetPath:String, ?defaultVariables:Map<String, String>)
return parseString(Assets.getText(assetPath), defaultVariables);
public static function parseString(data:String, ?defaultVariables:Map<String, String>) {
var trimmed:String;
var splitContent = [for(e in data.split("\n")) if ((trimmed = e.trim()) != "") trimmed];
var finalMap:Map<String, String> = [];
if (defaultVariables != null)
for(k=>e in defaultVariables)
finalMap[k] = e;
public static function parseString(data:String, ?defaultVariables:Map<String, String>) {
var trimmed:String;
var splitContent = [for(e in data.split("\n")) if ((trimmed = e.trim()) != "") trimmed];
for(line in splitContent) {
// comment
if (line.startsWith(";")) continue;
// categories; not supported yet
if (line.startsWith("[") && line.endsWith("]")) continue;
var finalMap:Map<String, String> = [];
if (defaultVariables != null)
for(k=>e in defaultVariables)
finalMap[k] = e;
var index = line.indexOf("=");
var name = line.substr(0, index).trim();
var value = line.substr(index+1).trim();
for(line in splitContent) {
// comment
if (line.startsWith(";")) continue;
// categories; not supported yet
if (line.startsWith("[") && line.endsWith("]")) continue;
if (value.startsWith("\"") && value.endsWith("\""))
value = value.substr(1, value.length - 2);
var index = line.indexOf("=");
var name = line.substr(0, index).trim();
var value = line.substr(index+1).trim();
if (value.length == 0 || name.length == 0)
continue;
finalMap[name] = value;
}
return finalMap;
}
if (value.startsWith("\"") && value.endsWith("\""))
value = value.substr(1, value.length - 2);
if (value.length == 0 || name.length == 0)
continue;
finalMap[name] = value;
}
return finalMap;
}
}
+75 -75
View File
@@ -4,84 +4,84 @@ import flixel.util.FlxColor;
import flixel.text.FlxText;
class MarkdownUtil {
public static function applyMarkdownText(text:FlxText, str:String) {
text.textField.htmlText = Markdown.markdownToHtml(prepareMarkdown(str));
var changes:Array<FlxTextFormatMarkerPair> = [
createAdvancedMarkerPair("{title}", 0xFFFFFFFF, text.size * 2, false, true, true),
createAdvancedMarkerPair("{subtitle}", 0xFFFFFFFF, text.size * 1.5, false, true, true),
createAdvancedMarkerPair("{subsubtitle}", 0xFFFFFFFF, text.size * 1.25, false, true, true),
createAdvancedMarkerPair("{ident1}", 0xFFFFFFFF, null, false, false, false, text.size * 2, true),
createAdvancedMarkerPair("{ident2}", 0xFFFFFFFF, null, false, false, false, text.size * 4, true),
createAdvancedMarkerPair("{ident3}", 0xFFFFFFFF, null, false, false, false, text.size * 6, true),
createAdvancedMarkerPair("{ident4}", 0xFFFFFFFF, null, false, false, false, text.size * 8, true),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFF00, false, true), "{o}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF0000, false, true), "{r}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF00FF08, false, true), "{g}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF7D7D7D, false, true), "{gray}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF222222), "{italic}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF666666), "{bold}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF888888), "{bold-italic}"),
];
public static function applyMarkdownText(text:FlxText, str:String) {
text.textField.htmlText = Markdown.markdownToHtml(prepareMarkdown(str));
var changes:Array<FlxTextFormatMarkerPair> = [
createAdvancedMarkerPair("{title}", 0xFFFFFFFF, text.size * 2, false, true, true),
createAdvancedMarkerPair("{subtitle}", 0xFFFFFFFF, text.size * 1.5, false, true, true),
createAdvancedMarkerPair("{subsubtitle}", 0xFFFFFFFF, text.size * 1.25, false, true, true),
createAdvancedMarkerPair("{ident1}", 0xFFFFFFFF, null, false, false, false, text.size * 2, true),
createAdvancedMarkerPair("{ident2}", 0xFFFFFFFF, null, false, false, false, text.size * 4, true),
createAdvancedMarkerPair("{ident3}", 0xFFFFFFFF, null, false, false, false, text.size * 6, true),
createAdvancedMarkerPair("{ident4}", 0xFFFFFFFF, null, false, false, false, text.size * 8, true),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFF00, false, true), "{o}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF0000, false, true), "{r}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF00FF08, false, true), "{g}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF7D7D7D, false, true), "{gray}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF222222), "{italic}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF666666), "{bold}"),
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF888888), "{bold-italic}"),
];
text.applyMarkup(
parseWarnings(text.textField.text),
changes
);
@:privateAccess {
// hacky fix for the text cutting when bigger text formats are used
text._regen = true;
text.regenGraphic();
text._regen = true;
text.regenGraphic();
}
}
text.applyMarkup(
parseWarnings(text.textField.text),
changes
);
@:privateAccess {
// hacky fix for the text cutting when bigger text formats are used
text._regen = true;
text.regenGraphic();
text._regen = true;
text.regenGraphic();
}
}
public static function createAdvancedMarkerPair(marker:String, color:FlxColor, size:Null<Float>, bold:Bool = false, italic:Bool = false, ?underline:Bool = false, ?blockIndent:Int, ?bullet:Bool) {
@:privateAccess {
var format = new FlxTextFormat(color, bold, italic);
format.format.size = size == null ? null : Std.int(size);
format.format.underline = underline;
format.format.blockIndent = blockIndent;
format.format.bullet = bullet;
return new FlxTextFormatMarkerPair(format, marker);
}
}
public static function createAdvancedMarkerPair(marker:String, color:FlxColor, size:Null<Float>, bold:Bool = false, italic:Bool = false, ?underline:Bool = false, ?blockIndent:Int, ?bullet:Bool) {
@:privateAccess {
var format = new FlxTextFormat(color, bold, italic);
format.format.size = size == null ? null : Std.int(size);
format.format.underline = underline;
format.format.blockIndent = blockIndent;
format.format.bullet = bullet;
return new FlxTextFormatMarkerPair(format, marker);
}
}
public static function parseWarnings(text:String) {
text = text.replace("&nbsp;", " ");
text = parseEmote(text, "⚠", "{o}(!)", "{o}");
text = parseEmote(text, "❌", "{r}(X)", "{r}");
text = parseEmote(text, "✔", "{g}(+)", "{g}");
return text;
}
public static function parseWarnings(text:String) {
text = text.replace("&nbsp;", " ");
text = parseEmote(text, "⚠", "{o}(!)", "{o}");
text = parseEmote(text, "❌", "{r}(X)", "{r}");
text = parseEmote(text, "✔", "{g}(+)", "{g}");
return text;
}
public static function prepareMarkdown(text:String) {
text = "\n" + text;
text = parseEmote(text, "\n- ", "\n{ident1}&nbsp;&nbsp;• ", "{ident1}");
text = parseEmote(text, "\n - ", "\n{ident2}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• ", "{ident2}");
text = parseEmote(text, "\n - ", "\n{ident3}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• ", "{ident3}");
text = parseEmote(text, "\n - ", "\n{ident4}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• ", "{ident4}");
text = parseEmote(text, "\n> ", "\n{gray}", "{gray}");
text = parseEmote(text, "\n### ", "\n{subsubtitle}", "{subsubtitle}");
text = parseEmote(text, "\n## ", "\n{subtitle}", "{subtitle}");
text = parseEmote(text, "\n# ", "\n{title}", "{title}");
text = parseEmote(text, "***", "{bold-italic}", "{bold-italic}", "***");
text = parseEmote(text, "**", "{bold}", "{bold}", "**");
text = parseEmote(text, "*", "{italic}", "{italic}", "*");
text = parseEmote(text, "_", "{italic}", "{italic}", "*");
text = parseEmote(text, "__", "{bold}", "{bold}", "*");
text.substr("\n".length);
return text;
}
public static function prepareMarkdown(text:String) {
text = "\n" + text;
text = parseEmote(text, "\n- ", "\n{ident1}&nbsp;&nbsp;• ", "{ident1}");
text = parseEmote(text, "\n - ", "\n{ident2}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• ", "{ident2}");
text = parseEmote(text, "\n - ", "\n{ident3}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• ", "{ident3}");
text = parseEmote(text, "\n - ", "\n{ident4}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• ", "{ident4}");
text = parseEmote(text, "\n> ", "\n{gray}", "{gray}");
text = parseEmote(text, "\n### ", "\n{subsubtitle}", "{subsubtitle}");
text = parseEmote(text, "\n## ", "\n{subtitle}", "{subtitle}");
text = parseEmote(text, "\n# ", "\n{title}", "{title}");
text = parseEmote(text, "***", "{bold-italic}", "{bold-italic}", "***");
text = parseEmote(text, "**", "{bold}", "{bold}", "**");
text = parseEmote(text, "*", "{italic}", "{italic}", "*");
text = parseEmote(text, "_", "{italic}", "{italic}", "*");
text = parseEmote(text, "__", "{bold}", "{bold}", "*");
text.substr("\n".length);
return text;
}
public static function parseEmote(text:String, emote:String, beginning:String, end:String, emoteEnd:String = "\n") {
var index:Int;
while((index = text.indexOf(emote)) >= 0) {
var nextIndex = text.indexOf(emoteEnd, index + emote.length);
if (nextIndex < 0)
nextIndex = text.length;
text = text.substr(0, index) + beginning + text.substring(index + emote.length, nextIndex) + end + (emote == emoteEnd ? "" : emoteEnd) + text.substring(nextIndex + emoteEnd.length);
}
return text;
}
public static function parseEmote(text:String, emote:String, beginning:String, end:String, emoteEnd:String = "\n") {
var index:Int;
while((index = text.indexOf(emote)) >= 0) {
var nextIndex = text.indexOf(emoteEnd, index + emote.length);
if (nextIndex < 0)
nextIndex = text.length;
text = text.substr(0, index) + beginning + text.substring(index + emote.length, nextIndex) + end + (emote == emoteEnd ? "" : emoteEnd) + text.substring(nextIndex + emoteEnd.length);
}
return text;
}
}
+1 -1
View File
@@ -30,7 +30,7 @@ class MemoryUtil {
}
public static function init() {}
public static function clearMinor() {
#if (cpp || java || neko)
Gc.run(false);
+45 -45
View File
@@ -4,12 +4,12 @@ import lime.app.Application;
/**
* Small util that allows you to load any function from ndlls via `getFunction`.
*
*
* NDLLs must be in your mod's "ndlls" folder, and must follow this name scheme:
* - `name-windows.ndll` for Windows targeted ndlls
* - `name-linux.ndll` for Linux targeted ndlls
* - `name-mac.ndll` for Mac targeted ndlls
*
*
* If:
* - The platform does not support NDLLs
* - The NDLL is not found
@@ -17,52 +17,52 @@ import lime.app.Application;
* then an empty function will be returned instead, and a message will be shown in logs.
*/
class NdllUtil {
#if NDLLS_SUPPORTED
#if windows public static final os:String = "windows"; #end
#if linux public static final os:String = "linux"; #end
#if macos public static final os:String = "mac"; #end
#if android public static final os:String = "android"; #end
#end
#if NDLLS_SUPPORTED
#if windows public static final os:String = "windows"; #end
#if linux public static final os:String = "linux"; #end
#if macos public static final os:String = "mac"; #end
#if android public static final os:String = "android"; #end
#end
/**
* Returns an function from a Haxe NDLL.
*
* @param ndll Name of the NDLL.
* @param name Name of the function.
* @param args Number of arguments of that function.
*/
public static function getFunction(ndll:String, name:String, args:Int) {
#if NDLLS_SUPPORTED
return getFunctionFromPath(Paths.ndll('$ndll-$os'), name, args);
#else
Logs.trace('NDLLs are not supported on this platform.', WARNING);
return function() {};
#end
}
/**
* Returns an function from a Haxe NDLL at specified path.
*
* @param ndll Asset path to the NDLL.
* @param name Name of the function.
* @param args Number of arguments of that function.
*/
public static function getFunctionFromPath(ndll:String, name:String, args:Int) {
#if NDLLS_SUPPORTED
if (!Assets.exists(ndll)) {
Logs.trace('Couldn\'t find ndll at ${ndll}.', WARNING);
return function() {};
/**
* Returns an function from a Haxe NDLL.
*
* @param ndll Name of the NDLL.
* @param name Name of the function.
* @param args Number of arguments of that function.
*/
public static function getFunction(ndll:String, name:String, args:Int) {
#if NDLLS_SUPPORTED
return getFunctionFromPath(Paths.ndll('$ndll-$os'), name, args);
#else
Logs.trace('NDLLs are not supported on this platform.', WARNING);
return function() {};
#end
}
/**
* Returns an function from a Haxe NDLL at specified path.
*
* @param ndll Asset path to the NDLL.
* @param name Name of the function.
* @param args Number of arguments of that function.
*/
public static function getFunctionFromPath(ndll:String, name:String, args:Int) {
#if NDLLS_SUPPORTED
if (!Assets.exists(ndll)) {
Logs.trace('Couldn\'t find ndll at ${ndll}.', WARNING);
return function() {};
}
var func = lime.system.CFFI.load(Assets.getPath(ndll), name, args);
if (func == null) {
if (func == null) {
Logs.trace('Method ${name} in ndll ${ndll} with ${args} args was not found.', ERROR);
return function() {};
return function() {};
}
return func;
#else
Logs.trace('NDLLs are not supported on this platform.', WARNING);
#end
return function() {};
}
return func;
#else
Logs.trace('NDLLs are not supported on this platform.', WARNING);
#end
return function() {};
}
}
+26 -26
View File
@@ -2,31 +2,31 @@ package funkin.utils;
#if ALLOW_MULTITHREADING
class ThreadUtil {
/**
* Creates a new Thread with an error handler.
* @param func Function to execute
* @param autoRestart Whenever the thread should auto restart itself after crashing.
*/
public static function createSafe(func:Void->Void, autoRestart:Bool = false) {
if (autoRestart) {
return sys.thread.Thread.create(function() {
while(true) {
try {
func();
} catch(e) {
trace(e.details());
}
}
});
} else {
return sys.thread.Thread.create(function() {
try {
func();
} catch(e) {
trace(e.details());
}
});
}
}
/**
* Creates a new Thread with an error handler.
* @param func Function to execute
* @param autoRestart Whenever the thread should auto restart itself after crashing.
*/
public static function createSafe(func:Void->Void, autoRestart:Bool = false) {
if (autoRestart) {
return sys.thread.Thread.create(function() {
while(true) {
try {
func();
} catch(e) {
trace(e.details());
}
}
});
} else {
return sys.thread.Thread.create(function() {
try {
func();
} catch(e) {
trace(e.details());
}
});
}
}
}
#end
+32 -32
View File
@@ -13,34 +13,34 @@ using StringTools;
*/
class XMLUtil {
/**
* Applies a property XML node to an object.
* @param object Object to which the xml property will be applied
* @param property `property` node.
*/
public static function applyXMLProperty(object:Dynamic, property:Access):ErrorCode {
if (!property.has.name || !property.has.type || !property.has.value) {
Logs.trace('Failed to apply XML property: XML Element misses name, type, or value attributes.', WARNING);
return MISSING_PROPERTY;
}
/**
* Applies a property XML node to an object.
* @param object Object to which the xml property will be applied
* @param property `property` node.
*/
public static function applyXMLProperty(object:Dynamic, property:Access):ErrorCode {
if (!property.has.name || !property.has.type || !property.has.value) {
Logs.trace('Failed to apply XML property: XML Element misses name, type, or value attributes.', WARNING);
return MISSING_PROPERTY;
}
var value:Dynamic = switch(property.att.type.toLowerCase()) {
case "float" | "number": Std.parseFloat(property.att.value);
case "int" | "integer" | "color": Std.parseInt(property.att.value);
case "string" | "str" | "text": property.att.value;
case "bool" | "boolean": property.att.value.toLowerCase() == "true";
default: return TYPE_INCORRECT;
}
if (value == null) return VALUE_NULL;
var value:Dynamic = switch(property.att.type.toLowerCase()) {
case "float" | "number": Std.parseFloat(property.att.value);
case "int" | "integer" | "color": Std.parseInt(property.att.value);
case "string" | "str" | "text": property.att.value;
case "bool" | "boolean": property.att.value.toLowerCase() == "true";
default: return TYPE_INCORRECT;
}
if (value == null) return VALUE_NULL;
try {
Reflect.setProperty(object, property.att.name, value);
} catch(e) {
Logs.trace('Failed to apply XML property: $e on ${Type.getClass(object)}', WARNING);
return REFLECT_ERROR;
}
return OK;
}
try {
Reflect.setProperty(object, property.att.name, value);
} catch(e) {
Logs.trace('Failed to apply XML property: $e on ${Type.getClass(object)}', WARNING);
return REFLECT_ERROR;
}
return OK;
}
/**
* Creates a new sprite based on a XML node.
@@ -69,11 +69,11 @@ class XMLUtil {
if (node.has.scrollx) {
var scroll:Null<Float> = Std.parseFloat(node.att.scrollx);
if (scroll != null) spr.scrollFactor.x = scroll;
}
}
if (node.has.scrolly) {
var scroll:Null<Float> = Std.parseFloat(node.att.scrolly);
if (scroll != null) spr.scrollFactor.y = scroll;
}
}
}
if (node.has.antialiasing) spr.antialiasing = node.att.antialiasing == "true";
if (node.has.scale) {
@@ -83,7 +83,7 @@ class XMLUtil {
if (node.has.updateHitbox && node.att.updateHitbox == "true") spr.updateHitbox();
spr.zoomFactor = Std.parseFloat(node.getAtt("zoomfactor")).getDefault(spr.zoomFactor);
for(anim in node.nodes.anim)
addXMLAnimation(spr, anim);
@@ -116,7 +116,7 @@ class XMLUtil {
if (i != null)
animData.indices.push(i);
}
}
}
return animData;
}
@@ -164,9 +164,9 @@ class XMLUtil {
// nothing
}
}
return OK;
return OK;
}
return MISSING_PROPERTY;
return MISSING_PROPERTY;
}
public static inline function fixXMLText(text:String) {
+191 -191
View File
@@ -24,81 +24,81 @@ using StringTools;
// import ZipUtils; var e = ZipUtils.createZipFile("gjnsdghs.ycemod"); ZipUtils.writeFolderToZip(e, "./mods/Friday Night Funkin'/", "Friday Night Funkin'/"); e.flush(); e.close();
class ZipUtil {
public static var bannedNames:Array<String> = [".git", ".gitignore", ".github", ".vscode", ".gitattributes", "readme.txt"];
public static var bannedNames:Array<String> = [".git", ".gitignore", ".github", ".vscode", ".gitattributes", "readme.txt"];
/**
* [Description] Uncompresses `zip` into the `destFolder` folder
* @param zip
* @param destFolder
* @param zip
* @param destFolder
*/
public static function uncompressZip(zip:Reader, destFolder:String, ?prefix:String, ?prog:ZipProgress):ZipProgress {
// we never know
FileSystem.createDirectory(destFolder);
var fields = zip.read();
var fields = zip.read();
try {
if (prefix != null) {
var f = fields;
fields = new List<Entry>();
for(field in f) {
if (field.fileName.startsWith(prefix)) {
fields.push(field);
}
}
}
if (prog == null)
prog = new ZipProgress();
prog.fileCount = fields.length;
for(k=>field in fields) {
prog.curFile = k;
var isFolder = field.fileName.endsWith("/") && field.fileSize == 0;
if (isFolder) {
FileSystem.createDirectory('${destFolder}/${field.fileName}');
} else {
var split = [for(e in field.fileName.split("/")) e.trim()];
split.pop();
FileSystem.createDirectory('${destFolder}/${split.join("/")}');
var data = unzip(field);
File.saveBytes('${destFolder}/${field.fileName}', data);
}
}
prog.curFile = fields.length;
prog.done = true;
} catch(e) {
prog.done = true;
prog.error = e;
}
return prog;
try {
if (prefix != null) {
var f = fields;
fields = new List<Entry>();
for(field in f) {
if (field.fileName.startsWith(prefix)) {
fields.push(field);
}
}
}
if (prog == null)
prog = new ZipProgress();
prog.fileCount = fields.length;
for(k=>field in fields) {
prog.curFile = k;
var isFolder = field.fileName.endsWith("/") && field.fileSize == 0;
if (isFolder) {
FileSystem.createDirectory('${destFolder}/${field.fileName}');
} else {
var split = [for(e in field.fileName.split("/")) e.trim()];
split.pop();
FileSystem.createDirectory('${destFolder}/${split.join("/")}');
var data = unzip(field);
File.saveBytes('${destFolder}/${field.fileName}', data);
}
}
prog.curFile = fields.length;
prog.done = true;
} catch(e) {
prog.done = true;
prog.error = e;
}
return prog;
}
#if (!macro && sys)
public static function uncompressZipAsync(zip:Reader, destFolder:String, ?prog:ZipProgress, ?prefix:String):ZipProgress {
if (prog == null)
prog = new ZipProgress();
Thread.create(function() {
uncompressZip(zip, destFolder, prefix, prog);
});
return prog;
}
#end
#if (!macro && sys)
public static function uncompressZipAsync(zip:Reader, destFolder:String, ?prog:ZipProgress, ?prefix:String):ZipProgress {
if (prog == null)
prog = new ZipProgress();
Thread.create(function() {
uncompressZip(zip, destFolder, prefix, prog);
});
return prog;
}
#end
/**
* [Description] Returns a `zip.Reader` instance from path.
* @param zipPath
* @return Reader
*/
public static function openZip(zipPath:String):Reader {
return new ZipReader(File.read(zipPath));
}
/**
* [Description] Returns a `zip.Reader` instance from path.
* @param zipPath
* @return Reader
*/
public static function openZip(zipPath:String):Reader {
return new ZipReader(File.read(zipPath));
}
/**
* [Description] Copy of haxe's Zip unzip function cause lime replaced it.
* @param f Zip entry
*/
public static function unzip(f:Entry) {
/**
* [Description] Copy of haxe's Zip unzip function cause lime replaced it.
* @param f Zip entry
*/
public static function unzip(f:Entry) {
if (!f.compressed)
return f.data;
var c = new haxe.zip.Uncompress(-15);
@@ -113,156 +113,156 @@ class ZipUtil {
return f.data;
}
/**
* [Description] Creates a ZIP file at the specified location and returns the Writer.
* @param path
* @return Writer
*/
public static function createZipFile(path:String):ZipWriter {
var output = File.write(path);
return new ZipWriter(output);
}
/**
* [Description] Creates a ZIP file at the specified location and returns the Writer.
* @param path
* @return Writer
*/
public static function createZipFile(path:String):ZipWriter {
var output = File.write(path);
return new ZipWriter(output);
}
/**
[Description] Writes the entirety of a folder to a zip file.
@param zip ZIP file to write to
@param path Folder path
@param prefix (Additional) allows you to set a prefix in the zip itself.
**/
public static function writeFolderToZip(zip:ZipWriter, path:String, ?prefix:String, ?prog:ZipProgress, ?whitelist:Array<String>):ZipProgress {
if (prefix == null) prefix = "";
if (whitelist == null) whitelist = [];
if (prog == null) prog = new ZipProgress();
/**
[Description] Writes the entirety of a folder to a zip file.
@param zip ZIP file to write to
@param path Folder path
@param prefix (Additional) allows you to set a prefix in the zip itself.
**/
public static function writeFolderToZip(zip:ZipWriter, path:String, ?prefix:String, ?prog:ZipProgress, ?whitelist:Array<String>):ZipProgress {
if (prefix == null) prefix = "";
if (whitelist == null) whitelist = [];
if (prog == null) prog = new ZipProgress();
try {
var curPath:Array<String> = ['$path'];
var destPath:Array<String> = [];
if (prefix != "") {
prefix = prefix.replace("\\", "/");
while(prefix.charAt(0) == "/") prefix = prefix.substr(1);
while(prefix.charAt(prefix.length-1) == "/") prefix = prefix.substr(0, prefix.length-1);
destPath.push(prefix);
}
var files:Array<StrNameLabel> = [];
var doFolder:Void->Void = null;
(doFolder = function() {
var path = curPath.join("/");
var zipPath = destPath.join("/");
for(e in FileSystem.readDirectory(path)) {
if (bannedNames.contains(e.toLowerCase()) && !whitelist.contains(e.toLowerCase())) continue;
if (FileSystem.isDirectory('$path/$e')) {
// is directory, so loop into that function again
for(p in [curPath, destPath]) p.push(e);
doFolder();
for(p in [curPath, destPath]) p.pop();
} else {
// is file, put it in the list
var zipPath = '$zipPath/$e';
while(zipPath.charAt(0) == "/") zipPath = zipPath.substr(1);
files.push(new StrNameLabel('$path/$e', zipPath));
}
}
})();
prog.fileCount = files.length;
for(k=>file in files) {
prog.curFile = k;
var fileContent = File.getBytes(file.name);
var fileInfo = FileSystem.stat(file.name);
var entry:Entry = {
fileName: file.label,
fileSize: fileInfo.size,
fileTime: Date.now(),
dataSize: 0,
data: fileContent,
crc32: Crc32.make(fileContent),
compressed: false
};
Tools.compress(entry, 1);
zip.writeFile(entry);
}
zip.writeCDR();
} catch(e) {
prog.error = e;
}
prog.done = true;
return prog;
}
try {
var curPath:Array<String> = ['$path'];
var destPath:Array<String> = [];
if (prefix != "") {
prefix = prefix.replace("\\", "/");
while(prefix.charAt(0) == "/") prefix = prefix.substr(1);
while(prefix.charAt(prefix.length-1) == "/") prefix = prefix.substr(0, prefix.length-1);
destPath.push(prefix);
}
public static function writeFolderToZipAsync(zip:ZipWriter, path:String, ?prefix:String):ZipProgress {
var zipProg = new ZipProgress();
Thread.create(function() {
writeFolderToZip(zip, path, prefix, zipProg);
});
return zipProg;
}
var files:Array<StrNameLabel> = [];
/**
* [Description] Converts an `Array<Entry>` to a `List<Entry>`.
* @param array
* @return List<Entry>
*/
public static function arrayToList(array:Array<Entry>):List<Entry> {
var list = new List<Entry>();
for(e in array) list.push(e);
return list;
}
var doFolder:Void->Void = null;
(doFolder = function() {
var path = curPath.join("/");
var zipPath = destPath.join("/");
for(e in FileSystem.readDirectory(path)) {
if (bannedNames.contains(e.toLowerCase()) && !whitelist.contains(e.toLowerCase())) continue;
if (FileSystem.isDirectory('$path/$e')) {
// is directory, so loop into that function again
for(p in [curPath, destPath]) p.push(e);
doFolder();
for(p in [curPath, destPath]) p.pop();
} else {
// is file, put it in the list
var zipPath = '$zipPath/$e';
while(zipPath.charAt(0) == "/") zipPath = zipPath.substr(1);
files.push(new StrNameLabel('$path/$e', zipPath));
}
}
})();
prog.fileCount = files.length;
for(k=>file in files) {
prog.curFile = k;
var fileContent = File.getBytes(file.name);
var fileInfo = FileSystem.stat(file.name);
var entry:Entry = {
fileName: file.label,
fileSize: fileInfo.size,
fileTime: Date.now(),
dataSize: 0,
data: fileContent,
crc32: Crc32.make(fileContent),
compressed: false
};
Tools.compress(entry, 1);
zip.writeFile(entry);
}
zip.writeCDR();
} catch(e) {
prog.error = e;
}
prog.done = true;
return prog;
}
public static function writeFolderToZipAsync(zip:ZipWriter, path:String, ?prefix:String):ZipProgress {
var zipProg = new ZipProgress();
Thread.create(function() {
writeFolderToZip(zip, path, prefix, zipProg);
});
return zipProg;
}
/**
* [Description] Converts an `Array<Entry>` to a `List<Entry>`.
* @param array
* @return List<Entry>
*/
public static function arrayToList(array:Array<Entry>):List<Entry> {
var list = new List<Entry>();
for(e in array) list.push(e);
return list;
}
}
class ZipProgress {
public var error:Exception = null;
public var curFile:Int = 0;
public var fileCount:Int = 0;
public var done:Bool = false;
public var percentage(get, null):Float;
public var error:Exception = null;
private function get_percentage() {
return fileCount <= 0 ? 0 : curFile / fileCount;
}
public var curFile:Int = 0;
public var fileCount:Int = 0;
public var done:Bool = false;
public var percentage(get, null):Float;
public function new() {}
private function get_percentage() {
return fileCount <= 0 ? 0 : curFile / fileCount;
}
public function new() {}
}
class ZipReader extends Reader {
public var files:List<Entry>;
public var files:List<Entry>;
public override function read() {
if (files != null) return files;
try {
var files = super.read();
return this.files = files;
} catch(e) {
}
return new List<Entry>();
}
public override function read() {
if (files != null) return files;
try {
var files = super.read();
return this.files = files;
} catch(e) {
}
return new List<Entry>();
}
}
class ZipWriter extends Writer {
public function flush() {
o.flush();
}
public function flush() {
o.flush();
}
public function writeFile(entry:Entry) {
writeEntryHeader(entry);
o.writeFullBytes(entry.data, 0, entry.data.length);
}
public function writeFile(entry:Entry) {
writeEntryHeader(entry);
o.writeFullBytes(entry.data, 0, entry.data.length);
}
public function close() {
o.close();
}
public function close() {
o.close();
}
}
class StrNameLabel {
public var name:String;
public var label:String;
public var name:String;
public var label:String;
public function new(name:String, label:String) {
this.name = name;
this.label = label;
}
public function new(name:String, label:String) {
this.name = name;
this.label = label;
}
}
#end