PoliticalWorldAPI Actions, Conditions и Effects
✅ Runtime verified — выполненные ветки WBML-0005 PoliticalWorldAPI 1.14.0
PoliticalWorldAPI позволяет аддону регистрировать политические действия, у которых есть:
metadata+ optional condition+ handler/effectДля новичка поток такой:
RegisterAction→ CanExecuteAction→ ExecuteAction / TryExecuteAction→ condition решает, можно ли запускать handler→ handler/effects меняют состояниеWBML-0005 проверял всю эту цепочку как единую подсистему.
ActionDefinition
Заголовок раздела «ActionDefinition»В изученном creator-source есть поля типа:
IdCategoryNameKeyDescriptionKeyDisplayNameDescriptionIconSortOrderKingdomCondition ConditionKingdomAction HandlerИзученный source старее runtime. WBML проверял API 1.14.0.
Минимальный пример
Заголовок раздела «Минимальный пример»private const string AddonId = "Example.Actions";private const string ActionId = AddonId + ".increase_counter";
PoliticalWorldAPI.RegisterAction( AddonId, new PoliticalWorldAPI.ActionDefinition { Id = ActionId, Category = "example", DisplayName = "Increase counter", Condition = kingdom => kingdom != null, Handler = kingdom => { int value = PoliticalWorldAPI.GetKingdomInt( kingdom, AddonId, "counter", 0);
PoliticalWorldAPI.SetKingdomInt( kingdom, AddonId, "counter", value + 1); } });ID action должен принадлежать namespace твоего аддона.
Validation, проверенный WBML-0005
Заголовок раздела «Validation, проверенный WBML-0005»Runtime API 1.14.0:
PW303 — чужой/unowned action ID → invalidPW304 — нет Handler → invalidPW305 — нет DisplayName/NameKey → warning, definition всё ещё validWarning о читаемом имени — не то же самое, что блокирующая registration error.
Важное правило runtime: тот же ID заменяет action
Заголовок раздела «Важное правило runtime: тот же ID заменяет action»Первый harness ожидал, что второй RegisterAction с тем же ID будет отклонён как duplicate.
Но API 1.14.0 сделал:
первая definition зарегистрирована→ второй RegisterAction с тем же ID вернул true→ GetAction показал вторую definition→ metadata/condition старой definition были замененыПосле этого Lab снова зарегистрировал canonical definition и проверил, что она восстановилась.
Для протестированного runtime это replacement/upsert semantics.
Практический риск: если случайно повторить ID, можно заменить собственный handler или condition вместо ожидаемой ошибки duplicate.
Queries и ActionInfo.Enabled
Заголовок раздела «Queries и ActionInfo.Enabled»WBML проверил:
GetActionGetActionsByAddonGetActionsByCategoryGetAddonContentSummaryДо cleanup canonical-набор содержал три action.
ActionInfo.Enabled менялся динамически после изменения данных, от которых зависела condition.
Combinator conditions
Заголовок раздела «Combinator conditions»На runtime 1.14.0 проверено:
All(true, null, true) → trueAll(true, false, true) → falseAny(false, null, true) → trueAny(empty) → trueNot(false) → trueNot(null) → trueОсобенно не стоит угадывать поведение Any(empty) и Not(null) — теперь оно записано как runtime-факт для этого стека.
Conditions по политическому состоянию
Заголовок раздела «Conditions по политическому состоянию»На текущем target kingdom прошли:
GovernmentIsIdeologyIsCurrentIsPoliticalSystemIsStabilityAtLeastStabilityAtMostЭто проверка helpers, а не утверждение, что конкретные ID тестового мира являются универсальными.
Conditions по данным аддона
Заголовок раздела «Conditions по данным аддона»WBML записал собственные значения и проверил:
AddonIntAtLeastAddonIntAtMostAddonBoolIsKingdomHasAddonTagТак можно делать actions, доступные только при нужном состоянии твоего аддона.
Party conditions
Заголовок раздела «Party conditions»Выполненные ветки:
PartySupportAtLeastHasRulingPartyHasActivePartyIdeologyПеред support-проверкой исправленный probe заново получил PartyInfo по стабильному ID. Старый info-объект не надо считать вечно актуальным.
CanExecuteAction, ExecuteAction, TryExecuteAction
Заголовок раздела «CanExecuteAction, ExecuteAction, TryExecuteAction»Для false condition:
CanExecuteAction → falseExecuteAction → falsehandler calls → 0TryExecuteAction → Success=falseCode → action-condition-failedДля true condition:
CanExecuteAction → trueExecuteAction → trueside effect → выполненTryExecuteAction → Success=trueCode → okПроверенные error codes:
missing action → action-not-foundnull kingdom → invalid-kingdomdisabled → action-condition-failedsuccess → okEffects.Sequence
Заголовок раздела «Effects.Sequence»Lab собрал последовательность:
SetAddonInt(counter, 10)nullChangeAddonInt(counter, +7)SetAddonBool(flag, true)AddAddonTag(tag)После action:
counter = 17flag = truetag presentПроверенные effect helpers
Заголовок раздела «Проверенные effect helpers»Прошли:
SetAddonIntChangeAddonIntSetAddonBoolAddAddonTagRemoveAddonTagChangeStabilitySetStabilitySetPartyRadicalismStability и radicalism менялись всего на ±1 и сразу восстанавливались.
Party support — особая опасность
Заголовок раздела «Party support — особая опасность»В раннем WBML-0005 у target kingdom была только одна активная партия. Попытка выставить ей support ниже 100 привела к:
100Попытка вернуть прежнее меньшее значение тем же setter снова дала 100.
Поэтому fix4 вообще не выполняет точную mutation support, если нет государства минимум с двумя активными партиями.
Статус:
👁 Observed: single-active-party path нормализует единственную партию до 100🧪 Не проверено: точная mutation/restoration при >=2 активных партияхНельзя документировать SetPartySupport как «всегда ставит ровно переданный процент».
Unregister
Заголовок раздела «Unregister»WBML проверил:
UnregisterAction(existing) → trueGetAction afterwards → nullCanExecuteAction → falseExecuteAction → falseвторой UnregisterAction → falseTryExecuteAction → action-not-foundLive owner query после cleanup дал count=0.
Caveat diagnostics
Заголовок раздела «Caveat diagnostics»Сразу после live query count=0 diagnostics всё ещё показал:
Registered actions: 2после истории repeated same-ID replacement.
Статус — 👁 Observed bookkeeping mismatch. Это не доказательство, что два action реально остались зарегистрированы: live query был пустым.
Финал WBML-0005
Заголовок раздела «Финал WBML-0005»PASS=90FAIL=0SKIP=3A=PASS B=PASS C=PASS D=PASSSUITE RESULT: PARTIAL PASSТри SKIP относятся только к точной ветке party-support mutation/restoration, которую безопасно не запускали в однопартийном состоянии.
Чеклист новичка
Заголовок раздела «Чеклист новичка»- Сначала зарегистрируй аддон.
- ID action держи внутри namespace аддона.
- Handler обязателен.
- Добавь читаемое имя.
- Не думай, что повтор того же ID обязательно даст ошибку.
- Проверяй результат выполнения, если failure важен.
- Для политического состояния перечитывай live data.
- Любые временные mutation обязаны безопасно восстанавливаться.
- С party support особенно осторожно в single-party state.