capabilities.properties = true.
Two functions, not three. The inverse of ApplyProperties is ApplyProperties, called
with the earlier record, so a third function would describe one function twice.
The bound
A value that silently did not stick becomes a restore that verifies as divergent, and the admin cannot tell whether the tool or the server is broken. This bound also decides what belongs inproperties at capture time: the set you capture is
the set you can restore. If you capture ammo you must be able to write ammo back and read
the same value. If you cannot, leave it out of Collect.
PrepareProperties
Phase 1. Answers, never writes.
{ ok = true, orientation, warnings } or { ok = false, code, reason }, with the
same rules as PrepareMaterialize: code is "unsupported" or
"invalid", reason is non-empty, and neither writes nor throws.
ApplyProperties
Phase 2. Conform, then read back.
Write everything, then read everything
When you write several keys, write them all first and read them all back afterwards, rather than interleaving. That matters for rollback. If a failure on a later key leaves the earlier ones already applied, the caller has to be able to conform the object back to the earlier record in one call, and it can only do that if the operation is shaped consistently.Things that are not properties
Anything you cannot read back
Anything you cannot read back
Write-only settings, values a third-party addon normalises on write, anything that lands
asynchronously. Leave them out of
Collect and they are not your problem.Structural changes
Structural changes
Blueprints’ own adapters refuse a model change rather than attempting one, because
swapping a model in place rebuilds the physics mesh, loses the motion state and
invalidates every constraint the entity is part of. The honest operation is a replace
(remove plus rebuild), and version 1.0 deliberately does not implement it.If a property of yours is structural in that way, refuse it in phase 1 with a reason that
names what would be needed.
Behavioural state
Behavioural state
The NPC adapter captures model, skin, health, max health and the held weapon, and
restores exactly those. It does not capture AI memory, schedule, enemy or navigation
state, so it never claims to restore them, and the verifier structurally cannot mention
them.Capture what you can restore. Anything else is a promise you will break.
Relationships
Relationships
Constraints, welds, ropes and parenting are not properties of one object. Nothing in
version 1.0 versions them, and an adapter that tried would be describing a graph in a
flat scalar map.
Partial is false, not partial
properties = true when most records work and some do not is not a partial capability, it is
a false one. Blueprints builds all-or-nothing group materialization and rollback-on-failure
on the promise, not on the average.
Declare less, and refuse the impossible cases in phase 1 with both a code and a non-empty
reason.
Blueprints’ own DarkRP adapter does not declare
properties, and the omission is the
honest part: the only non-spatial datum a job spawn carries is the job it belongs to, and
DarkRP exposes no way to move an existing spawn between jobs. Declaring it and re-inserting
the row under a different job would be a different spawn wearing an old identity.