diff --git a/README.md b/README.md
index 53854c0c..6bfc3b08 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,7 @@ haxelib install flixel
haxelib install flixel-addons
haxelib install flixel-ui
haxelib install hxvlc
+haxelib git moonchart https://github.com/MaybeMaru/moonchart
haxelib git haxeui-openfl https://github.com/haxeui/haxeui-openfl
haxelib git haxeui-core https://github.com/haxeui/haxeui-core
haxelib git maru-hscript https://github.com/MaybeMaru/hscript-improved
diff --git a/actions/libraries.json b/actions/libraries.json
index 3459d440..dfe6e7ab 100644
--- a/actions/libraries.json
+++ b/actions/libraries.json
@@ -49,6 +49,13 @@
"type": "install",
"version": null
},
+ {
+ "name": "moonchart",
+ "type": "git",
+ "dir": null,
+ "ref": "master",
+ "url": "https://github.com/MaybeMaru/moonchart"
+ },
{
"name": "maru-hscript",
"type": "git",
diff --git a/project.xml b/project.xml
index 997cc359..ad30a332 100644
--- a/project.xml
+++ b/project.xml
@@ -84,6 +84,7 @@
+
diff --git a/source/funkin/objects/NotesGroup.hx b/source/funkin/objects/NotesGroup.hx
index f603dd69..af830704 100644
--- a/source/funkin/objects/NotesGroup.hx
+++ b/source/funkin/objects/NotesGroup.hx
@@ -106,7 +106,8 @@ class NotesGroup extends Group
instance = this;
game = isPlayState ? PlayState.instance : null;
this.isPlayState = isPlayState;
- SONG = Song.checkSong(song, null, false); //Double check null values
+ //SONG = Song.checkSong(song, null, false); //Double check null values
+ SONG = song;
curSong = SONG.song;
if (isPlayState) {
diff --git a/source/funkin/states/PlayState.hx b/source/funkin/states/PlayState.hx
index 882026c1..67424648 100644
--- a/source/funkin/states/PlayState.hx
+++ b/source/funkin/states/PlayState.hx
@@ -38,7 +38,7 @@ class PlayState extends MusicBeatState
private var targetCamPos:FlxPoint;
private static var prevCamFollow:FlxObject;
- private var curSectionData:SectionJson;
+ private var curSectionData:Dynamic;
public var notesGroup:NotesGroup;
private var ratingGroup:RatingGroup;
@@ -140,7 +140,7 @@ class PlayState extends MusicBeatState
FlxG.cameras.setDefaultDrawTarget(camGame, true);
persistentUpdate = persistentDraw = true;
- SONG = Song.checkSong(SONG, null, false);
+ //SONG = Song.checkSong(SONG, null, false);
#if discord_rpc
detailsText = isStoryMode ? 'Story Mode: ${storyWeek.toUpperCase()}' : 'Freeplay';
@@ -363,7 +363,8 @@ class PlayState extends MusicBeatState
Conductor.songPosition = -Conductor.crochet * 5;
Conductor.setPitch(Conductor.songPitch);
- curSectionData = Song.checkSection(SONG.notes[0]);
+
+ curSectionData = SONG.notes[0];
cameraMovement();
if (skipCountdown) {
diff --git a/source/funkin/states/editors/ChartingState.hx b/source/funkin/states/editors/ChartingState.hx
index e9ee31d1..3cf8fa27 100644
--- a/source/funkin/states/editors/ChartingState.hx
+++ b/source/funkin/states/editors/ChartingState.hx
@@ -65,7 +65,7 @@ class ChartingState extends MusicBeatState
camTop = new FlxCamera(); camTop.bgColor.alpha = 0;
FlxG.cameras.add(camTop, false);
- SONG = Song.checkSong(PlayState.SONG);
+ SONG = PlayState.SONG;
notes = SONG.notes;
Conductor.offset = Vector.fromArrayCopy(SONG.offsets);
@@ -737,17 +737,19 @@ class ChartingState extends MusicBeatState
public function loadJson(song:String):Void {
stop();
- PlayState.SONG = Song.checkSong(Song.loadFromFile(PlayState.curDifficulty, song));
+ //PlayState.SONG = Song.checkSong(Song.loadFromFile(PlayState.curDifficulty, song));
+ PlayState.SONG = Song.loadFromFile(PlayState.curDifficulty, song);
FlxG.resetState();
}
public function loadAutosave():Void {
- PlayState.SONG = Song.checkSong(Song.parseJson('', autoSaveChart));
+ //PlayState.SONG = Song.checkSong(Song.parseJson('', autoSaveChart));
+ PlayState.SONG = Json.parse(autoSaveChart);//Song.parseJson('', autoSaveChart);
FlxG.resetState();
}
public function autosaveSong():Void {
- SONG = Song.checkSong(SONG);
+ //SONG = Song.checkSong(SONG);
autoSaveChart = getSongString();
SaveData.setSave('autoSaveChart', autoSaveChart);
SaveData.flushData();
@@ -767,8 +769,8 @@ class ChartingState extends MusicBeatState
}
}
- public function saveChart() {
- SONG = Song.checkSong(SONG);
+ public inline function saveChart()
+ {
saveJson(getSongString("\t"), PlayState.curDifficulty);
}
@@ -776,9 +778,12 @@ class ChartingState extends MusicBeatState
{
var metaEvents:Array = [];
notes.fastForEach((section, i) -> {
- metaEvents.push(section.sectionEvents.length <= 0 ? {} : {
- sectionEvents: section.sectionEvents.copy()
- });
+ if (section.sectionEvents.length > 0)
+ {
+ metaEvents.push(cast {
+ sectionEvents: section.sectionEvents.copy()
+ });
+ }
});
if (metaEvents.length > 1) {
@@ -789,14 +794,12 @@ class ChartingState extends MusicBeatState
else break;
}
}
-
- final meta:SongMeta = {
+
+ saveJson({
diffs: [PlayState.curDifficulty],
offsets: SONG.offsets.copy(),
events: metaEvents
- }
-
- saveJson(meta, "songMeta");
+ }, "songMeta");
}
override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array):Void
diff --git a/source/funkin/substates/NotesSubstate.hx b/source/funkin/substates/NotesSubstate.hx
index 451254cf..2cd40b82 100644
--- a/source/funkin/substates/NotesSubstate.hx
+++ b/source/funkin/substates/NotesSubstate.hx
@@ -15,7 +15,8 @@ class NotesSubstate extends MusicBeatSubstate
super(true, 0x98000000);
this.position = position;
- SONG = Song.checkSong(song);
+ //SONG = Song.checkSong(song);
+ SONG = song;
notesGroup = new NotesGroup(SONG, false);
notesGroup.skipStrumIntro = true;
notesGroup.init(position - 50);
diff --git a/source/funkin/util/backend/SongZip.hx b/source/funkin/util/backend/SongZip.hx
index 66673f8e..14d0ec8c 100644
--- a/source/funkin/util/backend/SongZip.hx
+++ b/source/funkin/util/backend/SongZip.hx
@@ -2,8 +2,6 @@ package funkin.util.backend;
import haxe.io.Path;
import flixel.util.FlxArrayUtil;
-import funkin.util.song.formats.QuaFormat;
-import funkin.util.song.formats.OsuFormat;
import funkin.states.editors.ModSetupState;
enum ZipFormat {
@@ -78,7 +76,7 @@ class SongZip {
}
static final UNZIP_FORMAT:Map = [
- "osu" => {
+ /*"osu" => {
getMap: function(chart) return cast new OsuFormat(chart),
convert: function(map) return OsuFormat.convertSong("", map),
title: "Title",
@@ -91,7 +89,7 @@ class SongZip {
title: "Title",
diff: "DifficultyName",
audio: "AudioFile"
- }
+ }*/
];
static function unzipFormat(format:String, modPath:String, zipFiles:Array) {
diff --git a/source/funkin/util/song/Song.hx b/source/funkin/util/song/Song.hx
index 59107961..49efd971 100644
--- a/source/funkin/util/song/Song.hx
+++ b/source/funkin/util/song/Song.hx
@@ -1,189 +1,74 @@
package funkin.util.song;
+import moonchart.backend.Optimizer;
import haxe.Json;
import flixel.util.FlxSort;
-import funkin.util.song.formats.OsuFormat;
-import funkin.util.song.formats.SmFormat;
-import funkin.util.song.formats.QuaFormat;
-import funkin.util.song.formats.GhFormat;
-import funkin.util.song.formats.FunkinFormat;
+import moonchart.backend.FormatDetector;
+import moonchart.formats.fnf.FNFMaru;
+import moonchart.formats.fnf.legacy.FNFLegacy;
-abstract NoteJson(Array) from Array to Array
-{
- public var time(get, set):Float;
- inline function set_time(value):Float return this[0] = value;
- inline function get_time():Float return this[0];
-
- public var lane(get, set):Int;
- inline function set_lane(value):Int return this[1] = value;
- inline function get_lane():Int return this[1];
-
- public var length(get, set):Float;
- inline function set_length(value):Float return this[2] = value;
- inline function get_length():Float return this[2] ?? 0;
-
- public var type(get, set):String;
- inline function set_type(value):String return this[3] = value;
- inline function get_type():String return this[3];
-
- public inline function push(value:Dynamic) this.push(value);
- public inline function pop() return this.pop();
-}
-
-abstract EventJson(Array) from Array to Array {
- public var time(get, set):Float;
- inline function set_time(value):Float return this[0] = value;
- inline function get_time():Float return this[0];
-
- public var name(get, set):String;
- inline function set_name(value):String return this[1] = value;
- inline function get_name():String return this[1];
-
- public var values(get, set):Array;
- inline function set_values(value):Array return this[2] = value;
- inline function get_values():Array return this[2];
-
- public inline function push(value:Dynamic) this.push(value);
- public inline function pop() return this.pop();
-}
-
-typedef SectionJson = {
- var ?sectionNotes:Array;
- var ?sectionEvents:Array;
- var ?mustHitSection:Bool;
- var ?bpm:Float;
- var ?changeBPM:Bool;
-}
-
-typedef SongJson = {
- var song:String;
- var notes:Array;
- var bpm:Float;
- var speed:Float;
- var offsets:Array;
- var stage:String;
- var players:Array;
-}
-
-typedef SongMeta = {
- var events:Array;
- var offsets:Array;
- var diffs:Array;
- //var bpm:Float;
-}
+typedef SongJson = FNFMaruJsonFormat;
+typedef SongMeta = FNFMaruMetaFormat;
+typedef SectionJson = FNFMaruSection;
+typedef NoteJson = FNFLegacyNote;
+typedef EventJson = FNFMaruEvent;
class Song
{
- private static final CHART_FORMATS:Array = [
- 'json', // Vanilla FNF
- 'osu', // Osu! Mania
- 'sm', 'ssc', // Stepmania
- 'qua', // Quaver
- 'chart' // Guitar Hero
- ];
-
public static function loadFromFile(diff:String, folder:String):SongJson
{
folder = formatSongFolder(folder);
-
- CHART_FORMATS.fastForEach((format, i) -> {
- final chartPath:String = Paths.chart(folder, diff, format);
- var meta = getSongMeta(folder);
- if (meta != null) meta = meta.diffs.contains(diff) ? meta : null; // Only use if diff is included
+
+ var formats:Array = [];
+
+ @:privateAccess
+ for (format => data in FormatDetector.formatMap)
+ {
+ if (formats.indexOf(data.extension) == -1)
+ formats.push(data.extension);
+ }
+
+ formats.fastForEach((format, i) ->
+ {
+ var chartPath:String = Paths.chart(folder, diff, format);
if (Paths.exists(chartPath, TEXT)) {
- switch (format) {
- case 'json': return checkSong(parseJson(chartPath), meta, true, diff); // Funkin chart
- case 'osu': return checkSong(OsuFormat.convertSong(chartPath), meta, false, diff); // Osu chart
- case 'sm' | 'ssc': return checkSong(SmFormat.convert(chartPath, diff), meta, false, diff); // Stepmania chart
- case 'qua': return checkSong(QuaFormat.convertSong(chartPath), meta, false, diff); // Quaver chart
- case 'chart': return checkSong(GhFormat.convertSong(chartPath), meta, false, diff); // Guitar hero chart
+
+ var format = FormatDetector.findFormat([chartPath]);
+ var maru:FNFMaru = new FNFMaru();
+
+ switch (format)
+ {
+ case FNF_MARU:
+ maru.fromFile(chartPath);
+ case _:
+ var chart = FormatDetector.createFormatInstance(format);
+ chart.fromFile(chartPath);
+ maru.fromFormat(chart);
}
- }
- });
- trace('$folder-$diff CHART NOT FOUND');
+ trace("LOADED CHART FROM FORMAT: " + format);
+ return maru.data.song;
+ }
+ });
- if (folder == "tutorial") if (diff == "hard") // Couldnt even find tutorial safe fail
+ // Couldnt even find tutorial safe fail
+ if (folder == "tutorial") if (diff == "hard")
{
- throw 'Failed to load chart';
+ throw 'Failed loading chart.';
return null;
}
+ trace('$folder-$diff CHART NOT FOUND');
return loadFromFile('hard', 'tutorial');
}
- inline public static function getSongMeta(song:String):Null {
+ public static function getSongMeta(song:String):Null {
var meta = CoolUtil.getFileContent(Paths.songMeta(song));
return meta.length > 0 ? cast Json.parse(meta) : null;
}
- //Check null values and remove unused format variables
- public static function checkSong(?song:SongJson, ?meta:SongMeta, checkEngine:Bool = false, diff:String = ""):SongJson
- {
- if (checkEngine) {
- meta = FunkinFormat.metaCheck(meta, diff);
- song = FunkinFormat.songCheck(song, meta, diff);
- }
-
- song = JsonUtil.checkJson(getDefaultSong(), song);
-
- if (song.notes.length != 0) {
- song.notes.fastForEach((section, i) -> {
- checkSection(section);
- if (section.sectionNotes.length > 100 && !CoolUtil.debugMode) // Fuck off
- return getDefaultSong();
- });
- }
- else {
- song.notes.push(getDefaultSection());
- }
-
- // Apply song metaData
- if (meta != null) {
- song.offsets = meta.offsets.copy();
-
- meta.events.fastForEach((section, s) -> {
- if (Reflect.hasField(section, "sectionEvents")) {
- section.sectionEvents.copy().fastForEach((event, e) -> {
- song.notes[s].sectionEvents.push(event);
- });
- }
- });
- }
-
- return song;
- }
-
- public static function checkSection(section:Null = null):SectionJson
- {
- section = JsonUtil.checkJson(getDefaultSection(), section);
- final foundNotes:Map = [];
- final uniqueNotes:Array> = []; // Skip duplicate notes
-
- section.sectionNotes.fastForEach((n, i) -> {
- var key = Math.floor(n[0]) + "-" + n[1] + "-" + n[3];
- if (!foundNotes.exists(key))
- {
- if (n[1] > Conductor.STRUMS_LENGTH - 1) // Convert extra key charts to 4 key
- {
- if (n[3] == null) n.push("default-extra");
- else if (n[3] == 0) n.unsafeSet(3, "default-extra");
- n.unsafeSet(1, n[1] % Conductor.STRUMS_LENGTH);
- }
-
- foundNotes.set(key, 0);
- uniqueNotes.push(n);
- }
- });
-
- foundNotes.clear();
- section.sectionNotes = uniqueNotes;
-
- return section;
- }
-
public static function getSectionTime(song:SongJson, section:Int = 0):Float {
var crochet:Float = (60000 / song.bpm);
var time:Float = 0;
@@ -233,72 +118,52 @@ class Song
}
//Removes unused variables for smaller size
- public static function optimizeJson(input:SongJson, metaClear:Bool = false):SongJson
+ public static function optimizeJson(input:SongJson):SongJson
{
var song:SongJson = JsonUtil.copyJson(input);
- song.notes.fastForEach((sec, i) -> {
- if (!sec.changeBPM) {
- Reflect.deleteField(sec, 'changeBPM');
- Reflect.deleteField(sec, 'bpm');
- }
- if (sec.sectionNotes.length <= 0) {
- Reflect.deleteField(sec, 'sectionNotes');
- }
- else
+ song.notes.fastForEach((section, i) ->
+ {
+ Optimizer.removeDefaultValues(section,
{
- sec.sectionNotes.fastForEach((note, i) -> {
- final type:String = Std.string(note[3]);
- if (type != null) if (type.length <= 0 || type == "default") {
- note.pop();
- }
- });
- sec.sectionNotes.sort(sortNotes);
- }
+ bpm: 0,
+ changeBPM: false,
+ mustHitSection: true,
+ sectionNotes: [],
+ sectionEvents: []
+ });
- if (sec.sectionEvents.length <= 0 || metaClear)
- Reflect.deleteField(sec, 'sectionEvents');
+ if (section.sectionNotes != null)
+ {
+ section.sectionNotes.fastForEach((note, i) ->
+ {
+ Optimizer.removeDefaultValues(note, {type: "default"});
+ });
- if (sec.mustHitSection)
- Reflect.deleteField(sec, 'mustHitSection');
+ section.sectionNotes.sort(sortNotes);
+ }
});
- if (song.notes.length > 1)
+ while (true)
{
- while (true) {
- final lastSec = song.notes[song.notes.length - 1];
- if (lastSec == null) break;
- if (Reflect.fields(lastSec).length <= 0) song.notes.pop();
- else break;
- }
- }
-
- if (metaClear) {
- Reflect.deleteField(song, 'offsets');
- //Reflect.deleteField(song, 'bpm');
- }
-
- return song;
- }
+ var lastSection = song.notes[song.notes.length - 1];
+
+ if (lastSection == null || Reflect.fields(lastSection).length > 0)
+ break;
- public static function parseJson(chartPath:String, rawJson:String = ""):SongJson
- {
- if (rawJson.length <= 0) {
- rawJson = CoolUtil.getFileContent(chartPath).trim();
- while (!rawJson.endsWith("}"))
- rawJson = rawJson.substr(0, rawJson.length - 1);
+ song.notes.pop();
}
- return cast Json.parse(rawJson).song;
+ return song;
}
/*
Use this function to get the sorted notes from a song as an array
Used for pico in Stress, but you can use it on other cool stuff
*/
- public static function getSongNotes(diff:String, song:String):Array>
+ public static function getSongNotes(diff:String, song:String):Array
{
- final notes:Array> = [];
+ final notes:Array = [];
loadFromFile(diff, song).notes.fastForEach((s, i) -> {
if (s.sectionNotes != null) {
@@ -312,8 +177,8 @@ class Song
return notes;
}
- private static function sortNotes(note1:Array, note2:Array):Int {
- return FlxSort.byValues(FlxSort.ASCENDING, note1[0], note2[0]);
+ private static inline function sortNotes(note1:NoteJson, note2:NoteJson):Int {
+ return FlxSort.byValues(FlxSort.ASCENDING, note1.time, note2.time);
}
public static function formatSongFolder(songName:String):String {
diff --git a/source/funkin/util/song/WeekSetup.hx b/source/funkin/util/song/WeekSetup.hx
index e4bfd515..5dc5f048 100644
--- a/source/funkin/util/song/WeekSetup.hx
+++ b/source/funkin/util/song/WeekSetup.hx
@@ -225,7 +225,8 @@ class WeekSetup
}
final song = PlayState.SONG;
- loadScreen.setupPlay(Stage.getJson(song.stage), song.players.copy(), song.song);
+ final players:Array = song.players;
+ loadScreen.setupPlay(Stage.getJson(song.stage), players.copy(), song.song);
Conductor.stop();
diff --git a/source/funkin/util/song/formats/BasicParser.hx b/source/funkin/util/song/formats/BasicParser.hx
deleted file mode 100644
index b3d3dc3d..00000000
--- a/source/funkin/util/song/formats/BasicParser.hx
+++ /dev/null
@@ -1,78 +0,0 @@
-package funkin.util.song.formats;
-
-typedef BasicBpmChange = {
- time:Float,
- bpm:Float
-}
-
-typedef ChartVar = {
- name:String,
- value:String
-}
-
-typedef BasicSection = {
- notes:Array>,
- bpm:Float // set to -1 if no changes
-}
-
-class BasicParser {
- var variables:Map = [];
- var bpmChanges:Array = [];
-
- var map:Array = [];
- var fnfMap:SongJson;
-
- public function new() {}
-
- public function convertSong(path:String, diff:String):SongJson {
- map = CoolUtil.getFileContent(path).split('\n');
- fnfMap = Song.getDefaultSong();
-
- __initVars();
- applyVars(variables, fnfMap);
- parseBpmChanges(map, bpmChanges);
-
- final split = path.split("/");
- fnfMap.song = split[split.length - 3];
- fnfMap.bpm = bpmChanges[0]?.bpm ?? 100.0;
-
- final sections = parseNotes(diff);
- if (sections != null) {
- for (section in sections) {
- final newSec:SectionJson = Song.getDefaultSection();
- newSec.sectionNotes = section.notes;
- newSec.changeBPM = section.bpm != -1;
- newSec.bpm = section.bpm;
-
- fnfMap.notes.push(newSec);
- }
- }
-
- return fnfMap;
- }
-
- function parseBpmChanges(map:Array, bpmChanges:Array):Void {}
-
- function applyVars(variables:Map, fnfMap:SongJson):Void {}
-
- function parseNotes(diff:String):Array {
- return null;
- }
-
- var doop:Int = 0;
-
- @:noCompletion
- function __initVars():Void {
- for (i in 0...map.length) {
- final _var = __resolveVar(map[i], i);
- if (_var != null) {
- variables.set(variables.exists(_var.name) ? _var.name + (doop++) : _var.name, _var.value);
- }
- }
- }
-
- @:noCompletion
- function __resolveVar(line:String, index:Int):ChartVar {
- return null;
- }
-}
\ No newline at end of file
diff --git a/source/funkin/util/song/formats/FunkinFormat.hx b/source/funkin/util/song/formats/FunkinFormat.hx
deleted file mode 100644
index 72e4d9d0..00000000
--- a/source/funkin/util/song/formats/FunkinFormat.hx
+++ /dev/null
@@ -1,112 +0,0 @@
-package funkin.util.song.formats;
-
-/*
- Kinda made only to not have all engine converter stuff in Song.hx
-*/
-
-class FunkinFormat
-{
- //Fixes charts from other engines
- public static function songCheck(?song:SongJson, meta:SongMeta, diff:String):SongJson
- {
- if (song == null)
- return song;
-
- //Get special engine variables ready if missing
- var specialFields:Array> = [
- ['players', ['bf','dad','gf']]
- ];
-
- for (field in specialFields) {
- if (!Reflect.hasField(song, field[0])) {
- Reflect.setField(song, field[0], field[1]);
- }
- }
-
- for (field in Reflect.fields(song)) {
- switch (field) {
- case 'gfVersion' | 'gf' | 'player3' | 'player2' | 'player1':
- final playerIndex:Int = switch(field) {
- case 'player1': 0;
- case 'player2': 1;
- default: 2;
- }
- final players:Array = Reflect.field(song, 'players');
- players[playerIndex] = Reflect.field(song, field);
- Reflect.setField(song, 'players', players);
- Reflect.deleteField(song, field);
- case 'events':
- final isFps = Reflect.hasField(Reflect.field(song, "events"), "events");
- song = isFps ? convertFpsChart(song) : convertPsychChart(song);
- Reflect.deleteField(song, field);
- }
- }
- return song;
- }
-
- public static function metaCheck(?meta:SongMeta, diff:String):SongMeta {
- if (meta == null)
- return meta;
-
- return meta;
- }
-
- // Converts FPS+ engine events
- public static function convertFpsChart(song:SongJson) {
- final fpsEvents:Array = Reflect.field(Reflect.field(song, "events"), "events");
- if (fpsEvents == null || fpsEvents.length <= 0) return song;
-
- final events:Map>> = [];
- for (e in fpsEvents) {
- if (!events.exists(e[0])) events.set(e[0], []);
- events.get(e[0]).push([e[1], e[3], []]);
- }
-
- for (i in events.keys()) {
- Song.checkAddSections(song, i);
- song.notes[i] = Song.checkSection(song.notes[i]);
- for (e in events.get(i))
- song.notes[i].sectionEvents.push(e);
- }
-
- return song;
- }
-
- // Converts psych and forever engine events
- public static function convertPsychChart(song:SongJson):SongJson {
- final psychEvents:Array = Reflect.field(song, 'events');
- if (psychEvents == null || psychEvents.length <= 0) return song;
-
- final events:Array> = [];
- for (e in psychEvents) {
- final eventTime = e[0];
- final _events:Array> = e[1];
- for (i in _events) events.push([eventTime, i[0], [i[1], i[2]]]);
- }
-
- for (i in events) {
- final eventSec = Song.getTimeSection(song, i[0]);
- Song.checkAddSections(song, eventSec);
- song.notes[eventSec] = Song.checkSection(song.notes[eventSec]);
- song.notes[eventSec].sectionEvents.push(i);
- }
-
- return song;
- }
-
- // Converts base game v-slice charts
- public static function convertVSliceSong(song:Dynamic, diff:String):SongJson
- {
- for (note in cast(Reflect.field(song.notes, diff), Array)) {
-
- }
-
-
- return song;
- }
-
- public static function convertVSliceMeta(meta:Dynamic, diff:String):SongMeta
- {
- return meta;
- }
-}
\ No newline at end of file
diff --git a/source/funkin/util/song/formats/GhFormat.hx b/source/funkin/util/song/formats/GhFormat.hx
deleted file mode 100644
index c69b0ee2..00000000
--- a/source/funkin/util/song/formats/GhFormat.hx
+++ /dev/null
@@ -1,97 +0,0 @@
-package funkin.util.song.formats;
-
-class GhFormat {
- public var map:Array = [];
- public function new(path:String) {
- map = CoolUtil.getFileContent(path).split('\n');
- }
-
- public static function convertSong(path:String, ?input:GhFormat):SongJson {
- var ghMap:GhFormat = input ?? new GhFormat(path);
- var fnfMap:SongJson = Song.getDefaultSong();
-
- final title = ghMap.getVar("Name");
- final bpmMap = ghMap.getBpmChanges();
- fnfMap.bpm = bpmMap.get(0);
-
- // Bpm changes crap
- var _sortedChanges:Array = [];
- for (i in bpmMap.keys()) {
- if (i <= 0) continue;
- _sortedChanges.push(i);
- }
- _sortedChanges.sort(function (a,b) return FlxSort.byValues(FlxSort.ASCENDING, a, b));
-
- for (i in _sortedChanges) {
- var _sec:Int = Song.getTimeSection(fnfMap, i)+1;
- Song.checkAddSections(fnfMap, _sec);
- fnfMap.notes[_sec].changeBPM = true;
- fnfMap.notes[_sec].bpm = bpmMap.get(i);
- }
-
- for (i in ghMap.getNotes()) {
- fnfMap.notes[Song.getTimeSection(fnfMap, i[0])].sectionNotes.push(i);
- }
-
- fnfMap.song = title;
-
- return fnfMap;
- }
-
- public function getVar(varName:String) {
- for (i in map) {
- if (i.startsWith(' $varName')) {
- var retVar = i.split('$varName = ')[1].trim();
- return Std.string(retVar.replace('\r','').replace('\n','').replace('"', ''));
- }
- }
- return null;
- }
-
- public function getBpmChanges():Map {
- var bpmChanges:Map = [];
- for (i in map) {
- if (i.contains(" = B ")) {
- var _split = i.split(" = B ");
- var time = Std.parseInt(_split[0]);
- var bpm = Std.parseInt(_split[1])/1000;
- bpmChanges.set(time, bpm);
- }
- }
- return bpmChanges;
- }
-
- public function getNotes() {
- var notes:Array> = [];
- var _bpm = getBpmChanges().get(0);
- var crochet:Float = (60 /_bpm) * 1000;
- var tickToMills = (60000 / (_bpm * Std.parseInt(getVar("Resolution"))));
-
- for (_ in 0...map.length) {
- if (map[_].startsWith("[ExpertSingle]")) {
- for (n in _+2...map.length) {
- if (map[n] == "}") break;
- if (map[n].contains("E") || map[n].contains("S")) continue;
-
- final _note = map[n].trim().replace(" = N ", " ");
- var note:Array = [];
- for (i in _note.split(" ")) {
- note.push(Std.parseInt(i));
- }
-
- note[0] *= tickToMills;
- if (note[2] > 0) {
- note[2] *= tickToMills;
- note[2] -= crochet * 0.25;
- } else {
- note[2] = 0;
- }
- notes.push(note);
- }
- break;
- }
- }
-
- return notes;
- }
-}
\ No newline at end of file
diff --git a/source/funkin/util/song/formats/OsuFormat.hx b/source/funkin/util/song/formats/OsuFormat.hx
deleted file mode 100644
index ef58f8be..00000000
--- a/source/funkin/util/song/formats/OsuFormat.hx
+++ /dev/null
@@ -1,99 +0,0 @@
-package funkin.util.song.formats;
-
-/*
- Custom made osu to fnf json format for mau engin
- DOES NOT CONVERT .OSZ FILES YET, ONLY .OSU CHART FILES!!!!!!
-*/
-
-class OsuFormat {
- public var map:Array = [];
- public function new(path:String) {
- map = CoolUtil.getFileContent(path).split('\n');
- }
-
- inline public static function convertSong(path:String, ?input:OsuFormat):SongJson {
- var osuMap:OsuFormat = input ?? new OsuFormat(path);
- var fnfMap:SongJson = Song.getDefaultSong();
-
- // Check if its not an osu!mania map
- final mode = Std.parseInt(osuMap.getVar('Mode'));
- if (mode != 3)
- return fnfMap;
-
- var title = osuMap.getVar('Title');
- var version = osuMap.getVar('Version');
- var timingPoints = osuMap.getTimingPoints();
- var offset = timingPoints[0];
- var bpm = FlxMath.roundDecimal(60000 / timingPoints[1], 1);
- var speed = Std.parseFloat(osuMap.getVar('OverallDifficulty'));
- var hitObjects = osuMap.getHitObjects();
-
- var sections:Array = [];
- for (i in 0...Lambda.count(hitObjects)) {
- var newSec:SectionJson = Song.getDefaultSection();
- if (hitObjects.get(i) != null)
- newSec.sectionNotes = hitObjects.get(i);
- sections.push(newSec);
- }
-
- fnfMap.song = title;
- fnfMap.notes = sections;
- fnfMap.bpm = bpm;
- fnfMap.offsets = [0,0];//[-offset,0];
- fnfMap.speed = FlxMath.roundDecimal(speed/2.5, 1);
- return fnfMap;
- }
-
- public function getVar(mapVar:String):Null {
- for (line in map) {
- if (line.startsWith(mapVar)) {
- var retVar:String = line.split('$mapVar:')[1].trim();
- return retVar.replace('\r','').replace('\n','');
- }
- }
- return null;
- }
-
- public function getTimingPoints():Array {
- for (i in 0...map.length) {
- if (map[i].startsWith('[TimingPoints]')) {
- var returnArray:Array = [];
- for (tm in map[i+1].split(','))
- returnArray.push(Std.parseFloat(tm));
- return returnArray;
- }
- }
- return [];
- }
-
- public function getHitObjects():Map>> {
- var returnMap:Map>> = new Map>>();
- var mapCircleSize = Std.parseInt(getVar('CircleSize'));
- var bpmMills = getTimingPoints()[1];
-
- for (l in 0...map.length) {
- if (map[l].startsWith('[HitObjects]')) {
- for (i in l...map.length-1) {
- if (!(map[i].length > 0 && map[i].contains(','))) continue; // Not a hit object, skip
- var hitObject:Array = [];
- var hitData = map[i].split(',');
- for (n in 0...hitData.length) {
- if (hitData[n].contains(':')) {
- hitData[n] = hitData[n].split(':')[0];
- }
- hitObject.push(Std.parseInt(hitData[n]));
- }
- var strumTime = hitObject[2];
- var noteData = Math.floor(hitObject[0] * mapCircleSize / 512);
- var susLength = (hitObject[5] > 0) ? (hitObject[5] - strumTime) : 0;
- var noteSec = Std.int(strumTime/(bpmMills*4));
- var noteSecArray = (returnMap.get(noteSec) != null) ? returnMap.get(noteSec) : [];
- noteSecArray.push([strumTime,noteData,susLength]);
- returnMap.set(noteSec, noteSecArray);
- }
- break;
- }
- }
- return returnMap;
- }
-}
\ No newline at end of file
diff --git a/source/funkin/util/song/formats/QuaFormat.hx b/source/funkin/util/song/formats/QuaFormat.hx
deleted file mode 100644
index 34231f47..00000000
--- a/source/funkin/util/song/formats/QuaFormat.hx
+++ /dev/null
@@ -1,80 +0,0 @@
-package funkin.util.song.formats;
-
-/*
- Custom made qua (quaver) to fnf json format for mau engin
- DOES NOT CONVERT .QP FILES YET, ONLY .QUA CHART FILES!!!!!!
-*/
-
-class QuaFormat {
- public var map:Array = [];
- public function new(path:String) {
- map = CoolUtil.getFileContent(path).split('\n');
- }
-
- public static function convertSong(path:String, ?input:QuaFormat):SongJson {
- var quaMap:QuaFormat = input ?? new QuaFormat(path);
- var fnfMap:SongJson = Song.getDefaultSong();
-
- // Check if map is above 4 keys
- if (quaMap.getVar('Mode') != 'Keys4') {
- return fnfMap;
- }
-
- var title = quaMap.getVar('Title');
- var bpm = FlxMath.roundDecimal(quaMap.getVar('Bpm'), 1);
- var speed = quaMap.getVar('InitialScrollVelocity');
- var hitObjects = quaMap.getHitObjects();
-
- var sections:Array = [];
- for (i in 0...Lambda.count(hitObjects)) {
- var newSec:SectionJson = Song.getDefaultSection();
- if (hitObjects.get(i) != null)
- newSec.sectionNotes = hitObjects.get(i);
- sections.push(newSec);
- }
-
- fnfMap.song = title;
- fnfMap.notes = sections;
- fnfMap.bpm = bpm;
- fnfMap.offsets = [0,0];//[-offset,0];
- fnfMap.speed = FlxMath.roundDecimal(speed, 1);
-
- return fnfMap;
- }
-
- public function getVar(mapVar:String):Dynamic {
- for (line in map) {
- if (line.startsWith('$mapVar: ') || line.startsWith('- $mapVar: ') || line.startsWith(' $mapVar:')) {
- var retVar:String = line.split('$mapVar: ')[1].trim();
- return Std.string(retVar.replace('\r','').replace('\n',''));
- }
- }
- return null;
- }
-
- public function getHitObjects():Map>> {
- var returnMap:Map>> = new Map>>();
- var crochet:Float = (60 / getVar('Bpm')) * 1000;
-
- for (l in 0...map.length) {
- if (map[l].startsWith('- StartTime: ')) {
- var strumTime = Std.parseInt(map[l].split('- StartTime: ')[1].trim());
- var noteData = Std.parseInt(map[l + 1].split(' Lane: ')[1].trim()) - 1;
- if (noteData >= 0) {
- var susLength = 0.0;
- if (map[l + 2].startsWith(' EndTime: ')) { // Get sus length if variable exists
- susLength = Std.parseInt(map[l + 2].split(' EndTime: ')[1].trim()) - strumTime;
- susLength -= crochet / 4;
- }
-
- var noteSec = Std.int(strumTime/(crochet*4));
- var noteSecArray = (returnMap.get(noteSec) != null) ? returnMap.get(noteSec) : [];
- noteSecArray.push([strumTime,noteData,susLength]);
- returnMap.set(noteSec, noteSecArray);
- }
- }
- }
-
- return returnMap;
- }
-}
\ No newline at end of file
diff --git a/source/funkin/util/song/formats/SmFormat.hx b/source/funkin/util/song/formats/SmFormat.hx
deleted file mode 100644
index 318fdfcb..00000000
--- a/source/funkin/util/song/formats/SmFormat.hx
+++ /dev/null
@@ -1,167 +0,0 @@
-package funkin.util.song.formats;
-
-import funkin.util.song.formats.BasicParser.ChartVar;
-import funkin.util.song.formats.BasicParser.BasicSection;
-import funkin.util.song.formats.BasicParser.BasicBpmChange;
-
-/**
- * Custom made sm (stepmania) to fnf json format for mau engin
- * @author maybemaru
- */
-
-class SmFormat extends BasicParser {
- public static function convert(path:String, diff:String):SongJson {
- return new SmFormat().convertSong(path, diff);
- }
-
- override function applyVars(variables:Map, fnfMap:SongJson) {
- fnfMap.offsets = [Std.int(Std.parseFloat(variables.get('OFFSET')) * -1000), 0];
- fnfMap.speed = 2.5;
- }
-
- override function parseBpmChanges(map:Array, bpmChanges:Array) {
- for (i in variables.get("BPMS").split(",")) {
- final data = i.split("=");
- bpmChanges.push({
- time: Std.parseFloat(data[0]) * 0.25, // Calculated in measures
- bpm: Std.parseFloat(data[1])
- });
- }
- }
-
- override function __resolveVar(line:String, index:Int):ChartVar {
- if (line.trim().startsWith("#")) {
- var varName:String = line.split(":")[0];
- varName = varName.substring(1, varName.length);
-
- var retVar:String = line.split('$varName:')[1].trim().replace('\r','').replace('\n','');
- if (!retVar.endsWith(";")) {
- index++;
- while (!map[index].endsWith(";") && !map[index].startsWith(";")) {
- var lineValue = map[index].trim().replace('\r','').replace('\n','');
- if (!lineValue.contains("// measure")) retVar += lineValue; // I have no idea why this exists, only makes parsing harder
- else retVar += ",";
-
- if (lineValue.length == 4) {
- retVar += "-";
- }
-
- index++;
-
- if (index > map.length) {
- throw("Couldnt get variable for " + varName);
- break;
- }
- }
- }
-
- return {
- name: varName,
- value: (retVar.endsWith(';')) ? retVar.substring(0, retVar.length - 1) : retVar
- }
- }
-
- return null;
- }
-
- var foundDiffs:Array = [];
-
- override function parseNotes(diff:String):Array {
- var baseNotes:Array = [];
- for (name => variable in variables) {
- if (name.startsWith("NOTES")) {
- baseNotes.push(variable);
- }
- }
-
- for (chart in baseNotes) {
- var parts = chart.split(":");
- var chartDiff:String = parts[2].toLowerCase();
- foundDiffs.push(chartDiff);
-
- if (diff == chartDiff) {
- return parseSm(parts[5].substr(0, parts[5].length - 1));
- }
- }
-
- throw("Couldn't find StepMania chart for difficulty " + diff + "\nFound difficulties " + foundDiffs.toString());
- return null;
- }
-
- function parseSm(notes:String):Array {
- // For ease of use, diving it
- var sections:Array> = [];
- for (sec in notes.split(",")) {
- sections.push(sec.split("-"));
- }
-
- var sectionsVector:Array = [];
- for (i in 0...sections.length) {
- sectionsVector.push({
- notes: [],
- bpm: -1
- });
- }
-
- var curBpm:Float = bpmChanges[0].bpm;
- bpmChanges.remove(bpmChanges[0]);
-
- var position:Float = 0.0;
- var measurePosition:Float = -1.0;
-
- var crochet:Float = 0.0;
-
- var recalc = function (index:Int) {
- crochet = (60 / curBpm) * (4 / sections[index].length) * 1000;
- }
-
- for (i in 0...sections.length) {
- recalc(i);
-
- for (l in 0...sections[i].length) {
- //Check for bpm changes
- if (bpmChanges[0] != null) {
- while (bpmChanges[0].time <= measurePosition) {
- curBpm = bpmChanges[0].bpm;
- sectionsVector[i].bpm = curBpm;
- recalc(i);
-
- bpmChanges.remove(bpmChanges[0]);
- if (bpmChanges[0] == null) break;
- }
- }
-
- // Add line notes
- var lineSplit = sections[i][l].split("");
- for (n in 0...lineSplit.length) {
- switch (lineSplit[n]) {
- case '1':// Normal note
- sectionsVector[i].notes.push([position, n, 0.0]);
- case '2':// Hold head
- sectionsVector[i].notes.push([position, n, resolveSustain(sections[i], l, n, crochet)]);
- case '4':// Roll head
- sectionsVector[i].notes.push([position, n, resolveSustain(sections[i], l, n, crochet), "roll"]);
- case 'M':// Mine
- sectionsVector[i].notes.push([position, n, 0.0, "mine"]);
- default:
- }
- }
-
- // Move conductor
- position += crochet;
- measurePosition += 1 / sections[i].length;
- }
- }
-
- return sectionsVector;
- }
-
- function resolveSustain(measure:Array, line:Int, index:Int, crochet:Float):Float {
- var length:Int = 1;
- for (i in line...measure.length) {
- if (measure[i].split("")[index] == "3") return length * crochet;
- length++;
- }
- return 0.0;
- }
-}
\ No newline at end of file