Edit RegistryMacro to automatically populate baseGameEntryIds list.

This commit is contained in:
EliteMasterEric
2025-04-15 20:25:18 -04:00
committed by Cameron Taylor
parent 14975212a9
commit 963e2ecd63
9 changed files with 109 additions and 137 deletions
+13
View File
@@ -190,6 +190,19 @@ abstract class BaseRegistry<T:(IRegistryEntry<J> & Constructible<EntryConstructo
return entries.get(id);
}
/**
* A list of all entries included in the base game.
* The actual function exists and is auto-generated on each registry at build time.
* @return Array<String>
*/
// public function listBaseGameEntryIds():Array<String> {}
/**
* A list of all entries that are not included in the base game.
* @return Array<String>
*/
// public function listModdedEntryIds():Array<String> {}
public function toString():String
{
return 'Registry(' + registryId + ', ${countEntries()} entries)';
@@ -18,8 +18,6 @@ class PlayerRegistry extends BaseRegistry<PlayableCharacter, PlayerData> impleme
public static final PLAYER_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
static final baseGamePlayerIds:Array<String> = funkin.util.macro.DataMacro.listBaseGamePlayerIds();
/**
* A mapping between stage character IDs and Freeplay playable character IDs.
*/
@@ -125,22 +123,4 @@ class PlayerRegistry extends BaseRegistry<PlayableCharacter, PlayerData> impleme
{
return ownedCharacterIds.exists(characterId);
}
/**
* A list of all the playable characters from the base game, in order.
*/
public function listBaseGamePlayerIds():Array<String>
{
return baseGamePlayerIds;
}
/**
* A list of all installed playable characters that are not from the base game.
*/
public function listModdedPlayerIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGamePlayerIds().indexOf(id) == -1;
});
}
}
-20
View File
@@ -42,8 +42,6 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> implements ISingleto
return '${Constants.TITLE} - ${Constants.VERSION}';
}
static final baseGameSongIds:Array<String> = funkin.util.macro.DataMacro.listBaseGameSongIds();
public function new()
{
super('SONG', 'songs', SONG_METADATA_VERSION_RULE);
@@ -484,24 +482,6 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> implements ISingleto
return chartData;
}
/**
* A list of all the story weeks from the base game, in order.
*/
public function listBaseGameSongIds():Array<String>
{
return baseGameSongIds;
}
/**
* A list of all installed story weeks that are not from the base game.
*/
public function listModdedSongIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGameSongIds().indexOf(id) == -1;
});
}
/**
* A list of all difficulties for a specific character.
*/
-20
View File
@@ -16,28 +16,8 @@ class StageRegistry extends BaseRegistry<Stage, StageData> implements ISingleton
public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <1.1.0";
static final baseGameStageIds:Array<String> = funkin.util.macro.DataMacro.listBaseGameStageIds();
public function new()
{
super('STAGE', 'stages', STAGE_DATA_VERSION_RULE);
}
/**
* A list of all the stages from the base game, in order.
*/
public function listBaseGameStageIds():Array<String>
{
return baseGameStageIds;
}
/**
* A list of all installed story weeks that are not from the base game.
*/
public function listModdedStageIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGameStageIds().indexOf(id) == -1;
});
}
}
+22 -16
View File
@@ -17,8 +17,6 @@ class LevelRegistry extends BaseRegistry<Level, LevelData> implements ISingleton
public static final LEVEL_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <1.1.0";
static final baseGameLevelIds:Array<String> = funkin.util.macro.DataMacro.listBaseGameLevelIds();
public function new()
{
super('LEVEL', 'levels', LEVEL_DATA_VERSION_RULE);
@@ -26,26 +24,34 @@ class LevelRegistry extends BaseRegistry<Level, LevelData> implements ISingleton
/**
* A list of all the story weeks from the base game, in order.
* @return Array<String>
*/
public function listBaseGameLevelIds():Array<String>
public function listBaseGameEntryIds():Array<String>
{
return baseGameLevelIds;
}
public function listSortedLevelIds():Array<String>
{
var result = listEntryIds();
result.sort(SortUtil.defaultsThenAlphabetically.bind(listBaseGameLevelIds()));
return result;
// This MUST be hard-coded (overriding the auto-generated method)
// because the auto-generated method spits out values in alphabetical order.
return [
'tutorial',
'week1',
'week2',
'week3',
'week4',
'week5',
'week6',
'week7',
'weekend1'
];
}
/**
* A list of all installed story weeks that are not from the base game.
* A list of all the story weeks in the game, in order.
* Modded levels are in alphabetical order at the end of the list.
* @return Array<String>
*/
public function listModdedLevelIds():Array<String>
public function listSortedLevelIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGameLevelIds().indexOf(id) == -1;
});
var result:Array<String> = listEntryIds();
result.sort(SortUtil.defaultsThenAlphabetically.bind(listBaseGameEntryIds()));
return result;
}
}
@@ -54,7 +54,7 @@ class ResultsDebugSubState extends MusicBeatSubState
FlxG.switchState(() -> new funkin.play.ResultState(resultsParams));
});
});
createToggleListItem("Character", PlayerRegistry.instance.listBaseGamePlayerIds(), function(result:String) {
createToggleListItem("Character", PlayerRegistry.instance.listBaseGameEntryIds(), function(result:String) {
resultsParams.characterId = result;
});
createToggleListItem("Results Mode", ["Debug", "Story", "Freeplay"], function(result:String) {
@@ -56,7 +56,7 @@ class WelcomeDialog extends Dialog
boxDrag.onClick = function(_) FileUtil.browseForSaveFile([FileUtil.FILE_FILTER_FNFS], loadFromFilePath, null, null, "Open Stage Data");
var defaultStages = StageRegistry.instance.listBaseGameStageIds();
var defaultStages:Array<String> = StageRegistry.instance.listBaseGameEntryIds();
defaultStages.sort(funkin.util.SortUtil.alphabetically);
for (stage in defaultStages)
-59
View File
@@ -1,59 +0,0 @@
package funkin.util.macro;
import haxe.macro.Expr;
#if macro
import sys.FileSystem;
#end
using StringTools;
class DataMacro
{
public static macro function listBaseGameStageIds():Expr
{
var folder = "assets/preload/data/stages/";
var files = FileSystem.readDirectory(folder);
var stages:Array<Expr> = [];
for (file in files)
stages.push(macro $v{file.replace(".json", "")});
return macro $a{stages};
}
public static macro function listBaseGameSongIds():Expr
{
var folder = "assets/songs/";
var files = FileSystem.readDirectory(folder);
var songs:Array<Expr> = [];
for (file in files)
songs.push(macro $v{file});
return macro $a{songs};
}
public static macro function listBaseGameLevelIds():Expr
{
var folder = "assets/preload/data/levels/";
var files = FileSystem.readDirectory(folder);
var levels:Array<Expr> = [];
for (file in files)
levels.push(macro $v{file.replace(".json", "")});
return macro $a{levels};
}
public static macro function listBaseGamePlayerIds():Expr
{
var folder = "assets/preload/data/players/";
var files = FileSystem.readDirectory(folder);
var players:Array<Expr> = [];
for (file in files)
players.push(macro $v{file.replace(".json", "")});
return macro $a{players};
}
}
+72
View File
@@ -8,6 +8,7 @@ import haxe.macro.Expr.TypeDefKind;
import haxe.macro.Expr.MetadataEntry;
import haxe.macro.Type;
import haxe.macro.Type.ClassType;
import sys.FileSystem;
using Lambda;
using haxe.macro.ExprTools;
@@ -38,6 +39,8 @@ typedef RegistryTypeParams =
*/
class RegistryMacro
{
static final DATA_FILE_BASE_PATH:String = 'assets/preload/data';
/**
* Builds the registry class.
*
@@ -139,8 +142,24 @@ class RegistryMacro
var createScriptedEntry:String = '${scriptedEntryClsName}.init(clsName, "unknown")';
var newJsonParser:String = 'new json2object.JsonParser<${dataType.module}.${dataType.name}>()';
var dataFilePath:String = getRegistryDataFilePath(cls, fields);
var baseGameEntryIds:Array<Expr> = listBaseGameEntryIds('${DATA_FILE_BASE_PATH}/${dataFilePath}/');
return (macro class TempClass
{
public function listBaseGameEntryIds():Array<String>
{
return $a{baseGameEntryIds};
}
public function listModdedEntryIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGameEntryIds().indexOf(id) == -1;
});
}
function getScriptedClassNames()
{
return ${Context.parse(getScriptedClassName, Context.currentPos())}.listScriptClasses();
@@ -300,6 +319,59 @@ class RegistryMacro
});
}
static function getRegistryDataFilePath(cls:ClassType, fields:Array<Field>):String
{
for (field in fields)
{
if (field.name == 'new')
{
// We found a field called `new`, it's probably the constructor.
switch (field.kind)
{
case FFun(f):
// Inside the function.
switch (f.expr.expr)
{
// Inside the block.
case EBlock(exprs):
var superCall:Expr = exprs[0];
switch (superCall.expr)
{
// Inside the super() call.
case ECall(_, args):
// var registryId:String = args[0].toString();
var dataPath:String = args[1].toString().replace('"', '').replace("'", '');
// var versionRule = args[2].toString();
return dataPath;
default:
Context.error('${cls.name}.new: RegistryMacro expected super call', field.pos);
}
default:
Context.error('${cls.name}.new: RegistryMacro expected super call', field.pos);
}
default:
// Continue looking for the actual constructor.
}
}
}
return '';
}
static function listBaseGameEntryIds(dataFilePath:String):Array<Expr>
{
var result:Array<Expr> = [];
var files:Array<String> = FileSystem.readDirectory(dataFilePath);
for (file in files)
{
result.push(macro $v{file.replace('.json', '')});
}
return result;
}
/**
* Check whether this class has already been processed by the RegistryMacro,
* as indicated by the `@:funkinProcessed` meta.