Skip to main content

Project configuration (project.hxp)

Phoenix Engine has no project.xml. The Lime project is a Haxe program — project.hxp, a Project extends HXProject class executed by the hxp library. Writing it in Haxe makes feature-flag logic expressible as real code instead of nested XML conditionals.

The constructor runs the configuration pipeline in order:

flair(); // print branch/commit banner
configureApp(); // metadata + window
displayTarget();
configureCompileDefines(); // non-feature haxedefs
configureFeatureFlags(); // the *_ALLOWED flags
configureOutputDir();
configureAndroidRuntime(); // pre-build callback for libc++_shared.so
configureHaxelibs(); // -lib entries, conditional on flags
configureAssets(); // asset libraries
configureIcons();

Metadata​

ConstantValue
VERSION"0.3.2" — the single source of truth; the game queries it at runtime
TITLEFriday Night Funkin' - Phoenix Engine
EXECUTABLE_NAMEFNF-Phoenix-Engine
PACKAGE_NAMEquack.fnf.phoenix
COMPANYJordanSantiago
MAIN_CLASSMain
PRELOADERflixel.system.FlxPreloader
SOURCE_DIRsource
Bumping the version

Change VERSION in project.hxp — every in-game reader (main menu, FPS counter, crash reports, the Lua phoenixVersion global) derives the Phoenix version from the application metadata it sets, and project.hxp also exposes it as the ENGINE_VERSION compile-time define. One manual step remains: make the first entry of THECHANGELOG.md the same version, because the update checker polls that file from this repository and compares its first entry against the running Phoenix version (#53, #54). tests/test_arena_fixes.py asserts the two stay equal.

Window​

Set in configureApp():

PropertyDesktopMobile
Size1280 × 7200 × 0 (native resolution)
FPS6060
Background0x0000000x000000
Hardwaretruetrue
VSyncfalsefalse
ResizabletrueAndroid true, iOS false
Orientation—LANDSCAPE

Feature flags​

A FeatureFlag is a string wrapper with enable/disable/apply/isEnabled helpers. apply(project, condition) sets the define unless the user already overrode it on the command line, so -DVIDEOS_ALLOWED or -DMODS_ALLOWED always wins.

FlagDefault conditionGuards
MODS_ALLOWEDdesktop or mobile, not web/flash/airthe whole mods/ pipeline (backend.Mods; otherwise backend.ModsStub)
LUA_ALLOWEDdesktop/mobile C++ targets (or forced by MODDING_LEVEL)psychlua.FunkinLua and all Lua callbacks
PYTHON_ALLOWEDsame as Lua, level 2 onlypsychlua.PythonScript and pystdlib
HSCRIPT_ALLOWEDdesktop, mobile, web (not flash/air)psychlua.HScript; also sets hscriptPos
VIDEOS_ALLOWEDdesktop/mobile C++, not 32-bit webhxvlc playback, cutscenes
SHADERS_ALLOWEDeverything except flash/airruntime shaders and the shaders/ package
DISCORD_ALLOWEDdesktop/mobile C++backend.DiscordClient
GAMEMODE_ALLOWEDLinux desktopFeral GameMode integration
ACHIEVEMENTS_ALLOWEDalwaysbackend.Achievements
CRASH_HANDLERalwaysbackend.CrashHandler and the crash report writer
CHECK_FOR_UPDATESalwaysthe outdated-version screen
FEATURE_FILE_DROPeverything except macOS/flash/airdrag-and-drop in the editors
FEATURE_DEBUG_FUNCTIONSopt-inextra debug menus
FUNNY_ALLOWEDdesktopeaster eggs
EMBED_ASSETSweb onlyembeds assets into the output
PRELOAD_ALLalwayspreloads asset libraries
NO_PRELOAD_ALLmanual -DNO_PRELOAD_ALL switchinverse of PRELOAD_ALL; assets are loaded on demand via states.LoadingState instead of preloaded (#55)
FLASH_ALLOWEDflash targetSWF-specific code paths
TITLE_SCREEN_EASTER_EGGcurrently commented outtitle screen easter egg
officialBuild-Dofficialmarks release builds

MODDING_LEVEL​

getModdingLevel() reads -DMODDING_LEVEL (checking both haxedefs and defines) and returns -1 when unset. When it is set it overrides the automatic conditions:

LevelLUA_ALLOWEDPYTHON_ALLOWED
0disableddisabled
1enableddisabled
2 (default on desktop)enabledenabled

Compile defines​

configureCompileDefines() sets haxedefs that are not feature flags:

DefineWhy
openfl-enable-handle-errorrequired by the crash logger
HXCPP_CHECK_POINTER, HXCPP_STACK_LINE, HXCPP_STACK_TRACE, HXCPP_CATCH_SEGVreadable native stack traces in crash reports
hscriptPosline numbers in HScript errors (when HSCRIPT_ALLOWED)
no-deprecation-warningsquieter builds
FLX_NO_FOCUS_LOST_SCREENthe engine draws its own
FLX_NO_PITCH, FLX_NO_SOUND_TRAYFlash/AIR only — those backends cannot pitch-shift
disable-version-checksuppresses OpenFL's Lime compatibility abort on SWF targets

Asset libraries​

configureAssets() registers Lime asset libraries. Each is embedded and/or preloaded depending on the target (web embeds, native streams):

LibrarySourceNotes
defaultassets/preloadalways loaded; menus, UI, base characters/charts
sharedassets/sharedshared between weeks
songsassets/songsinstrumentals and voices
videosassets/videosonly when VIDEOS_ALLOWED
week2 … week7, weekend1assets/week*per-week content

Global exclusions: .*, cvs, thumbs.db, desktop.ini, *.hash, *.md. Web builds additionally exclude *.ogg, native builds exclude *.mp3 — the engine picks the right extension at runtime through Paths.SOUND_EXT.

With -DNO_BUILTIN_CONTENT, the content libraries are stripped; see Building.

Class paths​

this.sources.push(SOURCE_DIR); // source/
this.sources.push("source/source-haxelib-patches"); // overrides, pushed LAST

Lime turns each entry into a -cp line after the library class paths, and the compiler takes a module from the last matching class path. That is the whole mechanism behind Haxelib patches — precedence is source/source-haxelib-patches/ > source/ > haxelib.

Build callbacks​

  • configureAndroidRuntime() registers a pre-build callback that runs setup/android-copy-stl.sh / .bat, copying libc++_shared.so from the NDK into build/<type>/android/bin/app/src/main/jniLibs/<abi>/. Lime runs pre-build callbacks after generating the Gradle project and before copying NDLLs — the only point where the file can still be added.
  • configureIcons() wires up art/icon16.png, icon32.png, icon64.png.
  • flair() prints the git branch, commit and dirty state into the build log, which is how backend.HaxeCommit can display the commit hash in-game.
FilePurpose
gamemode.iniFeral GameMode profile for Linux
modsList.txtwhich mods are enabled (<folder>|1 = enabled, 0 = disabled)
checkstyle.jsonHaxe Checkstyle rules
hxformat.jsonHaxe formatter rules
hmm.jsonpinned haxelib dependency list