Flamework
repository·master·Indexed 41 days ago
https://github.com/rbxts-flamework/coreAn extensible game framework for TypeScript in Roblox, providing high-level abstractions for game development. It features a dependency injection system with @Service and @Controller decorators, lifecycle hooks such as OnInit and OnStart, and a Modding API for runtime modifications and custom decorators. Version 1.3.2.
What's inside Flamework
- Flamework is an extensible game framework designed for use with TypeScript. It provides various abstractions and features to streamline game development.
Access Flamework documentation and installation guides
masterFor in-depth documentation, installation steps, and detailed guides, visit the official Flamework documentation website.
https://flamework.fireboltofdeath.dev/docs/introductionImplement lifecycle hooks
masterFlamework provides several interfaces to hook into the engine's lifecycle. Implementing these interfaces allows your Services or Controllers to perform logic at specific times:
OnInit: Called during startup. Use this for setup. You can return aPromise<void>to delay the initialization of other dependencies.OnStart: Called after allonInitcalls have completed. This is called asynchronously.OnTick: Equivalent toRunService.Heartbeat. Called every frame after physics.OnPhysics: Equivalent toRunService.Stepped. Called every frame before physics.OnRender: (Client only) Equivalent toRunService.RenderStepped. Called every frame before rendering.
@Service() export class MyLifecycleService implements OnInit, OnStart, OnTick { onInit() { print("Initializing..."); } onStart() { print("Started!"); } onTick(dt: number) { // Logic every frame } }Initialize Flamework with ignite()
masterCall
Flamework.ignite()to start the lifecycle events for all registered classes. This process resolves singletons, handles dependency ordering, and triggers lifecycle hooks likeonInitandonStart.Important: You must preload all necessary directories using
addPathsoraddPathsGlobbefore callingignite(). Any classes registered after ignition will not have their lifecycle events executed.Flamework.addPaths("ServerScriptService"); Flamework.ignite();Configure Flamework runtime settings
masterFlamework uses a configuration system generated by its transformer. You can control logging, profiling, and dependency warnings via the
Metadata.Configinterface. Configuration can be applied globally to thegameor scoped to specificpackagesusing their package IDs.Config Options
logLevel: Sets the verbosity of logs. Options are"none"or"verbose".profiling: A boolean determining if profiling is enabled. If not explicitly set, it defaults toRunService.IsStudio().disableDependencyWarnings: A boolean to suppress dependency-related warnings.
export interface Config { logLevel?: "none" | "verbose"; profiling?: boolean; disableDependencyWarnings?: boolean; }Retrieve metadata from an object
masterYou can retrieve metadata using either 'Own' methods (only looking at the target) or 'Inherited' methods (looking at the target and its parents).
Method Scope Description getOwnMetadata<T>(obj, key, property?)Own Returns the value for the key, or undefinedif not found.getMetadata<T>(obj, key, property?)Inherited Returns the first value found in the hierarchy. getMetadatas<T>(obj, key, property?)Inherited Returns an array of ALL values found in the hierarchy for that key. hasMetadata(obj, key, property?)Inherited Returns trueif the key exists on the object or its parents.hasOwnMetadata(obj, key, property?)Own Returns trueif the key exists specifically on the object/property.// Get a single value from the hierarchy const val = Reflect.getMetadata<string>(myObj, "version"); // Get all values (e.g., if multiple classes in a hierarchy define it) const allVals = Reflect.getMetadatas<string>(myObj, "tags"); // Check existence if (Reflect.hasMetadata(myObj, "isInitialized")) { // ... }Create metadata-only decorators with createMetaDecorator
masterIf you only need to attach metadata to a class, method, or property without executing logic at the time of decoration, use
Modding.createMetaDecorator. These decorators are more lightweight as they only perform the metadata registration step.const myMetaDecorator = Modding.createMetaDecorator("Class"); @myMetaDecorator class MyMetadataClass {}Mark a singleton as Optional
masterApply the
@Optionaldecorator to a@Serviceor@Controller. An optional singleton will only be instantiated if it is explicitly depended upon by another class or if it is manually included usingFlamework.includeOptionalClass(ctor).@Service() @Optional export class MyOptionalService implements OnInit { onInit() {} }Inspect decorators with getDecorator and getPropertyDecorators
masterYou can retrieve metadata attached via decorators using the following methods:
getDecorator(object, property?, id?): Retrieves the arguments of a specific decorator on an object or a specific property of that object.getPropertyDecorators(obj, id?): Returns aMapof all properties on an object that are decorated with the specified decorator ID.getDecorators(id?): Retrieves all objects currently associated with a specific decorator ID.
// Get arguments from a specific property decorator const config = Modding.getDecorator(myInstance, "myProperty", "my_decorator_id"); if (config) { print(config.arguments); } // Get all properties on an object using a specific decorator const propMap = Modding.getPropertyDecorators(myInstance, "my_decorator_id"); for (const [propName, data] of propMap) { print(`${propName} has config:`, data.arguments); }Resolve singletons with resolveSingleton
masterUse
Modding.resolveSingleton(ctor)to retrieve an existing instance of a class or instantiate it if it does not yet exist. This is the primary way to access Flamework-managed singletons.Note: This method will throw an error if a circular dependency is detected during resolution.
class MyService { // ... } // Retrieves the singleton instance of MyService const service = Modding.resolveSingleton(MyService);Listen for lifecycle and decorator events
masterThe
Moddingnamespace provides mechanisms to react when objects are registered with specific lifecycle events or decorators.Listen for any listener being added
Use
Modding.onListenerAdded(func)to trigger a callback whenever any object is registered in the system.Listen for specific decorators or lifecycle events
Pass an
id(either a string or anIdRef) toonListenerAddedto filter for specific events. This is useful for building plugins or tools that react to specific Flamework behaviors.Listen for listener removal
Use
Modding.onListenerRemoved(func)to react when an object is removed from the system. You can also provide anidto filter for specific removals.// Listen for any object being added Modding.onListenerAdded((obj) => { print("A new object was registered:", obj); }); // Listen specifically for when an object with a specific decorator ID is added Modding.onListenerAdded((obj) => { print("An object with the target decorator was added:", obj); }, "my_decorator_id"); // Listen for removals Modding.onListenerRemoved((obj) => { print("An object was removed:", obj); });Use the Dependency macro
masterThe
Dependency<T>()macro allows you to retrieve a dependency outside of the standard constructor-based dependency injection lifecycle.Warning: This is recommended to be used minimally as it can make code harder to test or stub. It is preferred to pass dependencies into your classes via their constructors.
// Example of manual dependency resolution const myService = Dependency<MyService>();