Interface Component<T>
- Type Parameters:
T
- The type of argument that can be passed when enabling this component
- All Known Implementing Classes:
NWindowManagerComponent
,PlayerManagerComponent
,StallingComponent
ComponentManager
.
Components are composed of various fragments that define their behavior and capabilities.
Components can be attached and detached from a ComponentManager
and can be enabled or disabled with
specific arguments. They can also define a slot for mutually exclusive components.
Component Lifecycle
- Attached:
onAttached(ComponentManager, Runner, DataStoreProvider)
is called when the component is first added to the manager - Enabled:
onEnable(ComponentManager, Runner, DataStoreProvider, boolean, Object)
is called when the component and all its dependencies are ready - Nudged:
onNudge(ComponentManager, Runner, DataStoreProvider, boolean, Object)
is called when the component is scheduled to be enabled but has pending dependencies - Disabled:
onDisable(ComponentManager, Runner, DataStoreProvider)
is called when the component is explicitly disabled or when one of its dependencies is disabled - Detached:
onDetached(ComponentManager, Runner, DataStoreProvider)
is called when the component is removed from the manager
Dependency System
Components can depend on other components and will only be enabled when all their dependencies are enabled. Dependencies are specified when adding a component to the manager:
manager.addComponent(myComponent, dependency1, dependency2, ...);
If any dependency is disabled, components that depend on it will automatically be disabled as well. When dependencies become available again, dependent components will not automatically re-enable; they must be explicitly enabled again.
Best Practices
- Implement primary component logic in
onEnable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider, boolean, T)
and fragment update methods - Use
onAttached(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider)
only for initialization that must happen before enabling - The receiveXXX methods from fragments should be used only to store instance fields
- The loadXXX methods should be used only for resource creation or loading, or to configure what is directly passed to them. This will avoid concurrency issues, as some of these methods may run on different threads than the rest of the component.
onDisable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider)
should reset state to allow future re-enabling. $onDisable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider)
is always called automatically before an enabled component is detachedonDetached(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider)
must thoroughly clean up all resources to prevent memory leaks
For a detailed explaination of the component lifecycle and methods execution order, see the
Fragment
class.
It is usually a good approach to ignore the onAttached(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider)
and onDetached(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider)
methods and
implement all the logic in onEnable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider, boolean, T)
and onDisable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider)
, so that when the component is
disabled, everything that was set up in onEnable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider, boolean, T)
is cleaned up in onDisable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider)
. Unless you
are dealing with heavy initialization logic, this will help keeping the code clean and concise.
-
Method Summary
Modifier and TypeMethodDescriptiondefault String
getId()
Returns an identifier for this component, multiple component can have the same identifier.default Object
getSlot()
Returns the slot associated with this component.default void
onAttached
(ComponentManager mng, Runner runner, DataStoreProvider dataStore) Called immediately when the component is attached to aComponentManager
and aRunner
.default void
onDetached
(ComponentManager mng, Runner runner, DataStoreProvider dataStore) Called when the component is detached from theComponentManager
.void
onDisable
(ComponentManager mng, Runner runner, DataStoreProvider dataStore) Called when the component is disabled.void
onEnable
(ComponentManager mng, Runner runner, DataStoreProvider dataStore, boolean firstTime, T arg) Called when the component is enabled.default void
onNudge
(ComponentManager mng, Runner runner, DataStoreProvider dataStore, boolean firstTime, T arg) Called when the component is scheduled to be enabled but cannot be due to unsatisfied dependencies.
-
Method Details
-
onAttached
Called immediately when the component is attached to aComponentManager
and aRunner
.This method can be overridden to perform initialization tasks when the component is attached.
- Parameters:
mng
- the ComponentManager to which this component is attachedrunner
- the Runner associated with this componentdataStore
- the DataStoreProvider for accessing shared data
-
onDetached
Called when the component is detached from theComponentManager
.This method can be overridden to perform cleanup tasks when the component is detached.
- Parameters:
mng
-runner
-dataStore
-
-
getId
Returns an identifier for this component, multiple component can have the same identifier.The default implementation returns the simple name of the class. This can be overridden to provide a custom identifier if needed.
- Returns:
- an identifier for this component, default is the simple class name
-
getSlot
Returns the slot associated with this component.A slot represents a mutually exclusive container for components. Only one component can be active in a given slot at any time. When a component with a defined slot is enabled, any other active component occupying the same slot will be automatically disabled.
IfgetSlot()
returnsnull
, the component is excluded from slot-based management and can coexist with other components.- Returns:
- the name of the slot this component belongs to, or
null
if it does not use a slot
-
onEnable
void onEnable(ComponentManager mng, Runner runner, DataStoreProvider dataStore, boolean firstTime, T arg) Called when the component is enabled. This is the most important method of the component lifecycle, where the component's main logic is implemented.This method is called when the component is enabled, all its dependencies are satisfied, the fragments are initialized, and the resources are loaded.
- Parameters:
mng
- - the ComponentManager to which this component is attachedrunner
- - the Runner that executes the logicdataStore
- - the DataStoreProvider for storing and retrieving data and cachesfirstTime
- - whether this is the first time the component is being enabledarg
- - an argument that can be passed when enabling this component, can be null
-
onDisable
Called when the component is disabled.This should undo anything that was done in
onEnable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider, boolean, T)
and reset the component state to allow future re-enabling.This method is called when the component is explicitly disabled or when one of its dependencies is disabled.
If $
invalid reference
#onDetach
It is always called before an enabled component is detached from the
ComponentManager
.- Parameters:
mng
-runner
-dataStore
-
-
onNudge
default void onNudge(ComponentManager mng, Runner runner, DataStoreProvider dataStore, boolean firstTime, T arg) Called when the component is scheduled to be enabled but cannot be due to unsatisfied dependencies.This method provides an opportunity for the component to take action when it's waiting on dependencies. Unlike
onEnable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider, boolean, T)
, which is only called when all dependencies are satisfied,onNudge
is called when the component manager attempts to enable the component but one or more dependencies are not yet enabled.This can be used to implement "smart" components that can enable their own dependencies or adapt to missing dependencies. For example, a GameMapComponent might depend on a GameTerrainComponent. When a user tries to enable the GameMapComponent, it could use this method to detect and enable its terrain dependency automatically.
The method receives the same parameters as
onEnable(org.ngengine.components.ComponentManager, org.ngengine.runner.Runner, org.ngengine.store.DataStoreProvider, boolean, T)
, allowing components to perform partial initialization or setup temporary alternatives while waiting for dependencies.- Parameters:
mng
- the ComponentManager that manages this componentrunner
- the Runner that provides execution contextdataStore
- the DataStoreProvider for accessing persistent datafirstTime
- whether this is the first attempt to enable this componentarg
- an optional argument passed when enabling this component
-