Component construction#
Derived components use Nupp's own field defaults and constructors. A value made with new goes directly into world:spawn or world:set:
(tecs.ecs.Component)
local struct Health
value: number = 100
max: number = 100
end
local entity = world:spawn(new Health(80, 120))
world:batchSpawn(100, {Health})The derive publishes an initializer so default additions and bulk spawns use the same initialization rules. Native bulk defaults initialize rows in place. Registration inspects the declaration and never evaluates a user constructor. Reusable initializers require one unambiguous construction path. Nupp rejects multiple constructors, generic owners, affine fields, and constructors that let self escape or transfer owned arguments into fields. Such declarations can instead use an explicit named factory without the ECS derive.
Factory configuration#
Use a factory when a separate component identity or custom call shape is useful.
Component(...)calls the registeredconstructfunction and carries the result across a spawn or set boundary.defaultreturns a fresh value when the component is added without a value.world:getreturns the stored value, or nil when the entity lacks it.
Positional fields#
local record HealthValue
value: number
max: number
end
local Health = tecs.ecs.newComponent(HealthValue, {
name = "Health",
construct = function(value: number?, maximum: number?): HealthValue
return new HealthValue(value = value or 100, max = maximum or 100)
end,
default = function(): HealthValue
return new HealthValue(value = 100, max = 100)
end,
})
local full = Health()
local damaged = Health(80, 120)Defaults belong in the constructor. A false value is a valid boolean default; do not use value or true when false must be preserved.
Named construction#
Use a typed options record as the constructor argument when names make a call clearer. Create Nupp records with new Record(field = value). The ECS definition wraps factory-created values supplied to world:spawn or world:set. Values of derived declarations need no wrapper.
Validation and derived values#
Use defaults for static values. Validate, normalize, and calculate derived state inside the constructor before it returns. Put shared initialization in one helper and call it from construct and default.
Custom call shapes#
Constructor arguments can describe an operation rather than a field list. For example, an emitter constructor can accept a typed effect configuration and return the record a system will later read. See Record components.