Specific activable component condition (for conditional components conditions and area victory conditions)
Feature: Specific Activable component condition for Conditional Components and Area Victory Conditions
Plan d'implémentation généré (pas encore relu): 471.zip
Summary
Add a new detection mode DETECTION_SPECIFIC_ACTIVABLE_COMPONENT to both conditional blocks (IDetectionComponent) and area victory conditions. This condition mirrors the active/inactive state of another component within the same area.
UI
When this mode is selected (in ComponentConditionsMenuInventory or AreaConditionsMenuInventory — same layout for both), instead of the usual range (min/max) controls, 4 items are displayed:
- A button to open a shortcut bar for selecting the target component (similar to the solidifier's sender selection shortcut bar; texture: TO CREATE, use
COMPONENT_MENU_CONDITIONS_OPEN_MENUas placeholder). - A non-clickable label (texture: same as
COMPONENT_MENU_CONDITIONS_OPEN_MENU). - A checkbox: if checked → activated when target is activated; if unchecked → activated when target is NOT activated.
- A teleport button (texture: same as
SOLIDIFIER_TARGET_SENDERS_TELEPORT).
Constraints
-
Storage: New database fields required for both
ComponentEntityandAreaEntity. Do not reuse existing fields. - Same area: The target must belong to the same area.
- Not self: A component cannot target itself.
-
Target must be activable: Must implement a future
IActivableComponentinterface (see below). - Loop detection: Circular references (A → B → … → A) must be detected and rejected at selection time. Requires graph cycle detection (transitive walk).
- Lifecycle ordering: A 0–1 tick delay between source and dependent activation is expected (or N ticks for chained conditions). Out of scope for now.
Edge cases
- Targeted component is deleted → clean up the reference (reset mode or clear target). Note:
LaserSolidifierhas the same bug today (danglingtargetSenderIdswhen a sender is deleted) — fix both. - User switches to another detection mode → clear the stored target.
Schematics
Component IDs change during paste, so target references become dangling. This is the same unsolved problem as LaserSolidifier.targetSenderIds (IDs are not remapped today). Fix solidifier schematic remapping in the same scope.
Activable components
A new IActivableComponent interface with boolean isActivated() is needed. Many components have an active/inactive state but use different method names today.
Eligible components
| Component | Current method | State semantics |
|---|---|---|
| LaserSender |
isActivated() (via IDetectionComponent) |
Active per its own DetectionMode
|
| WinnerBlock |
isActivated() (via IDetectionComponent) |
Active when receiver count ∈ [min, max] |
| AppearingWinnerBlock |
isActivated() (via IDetectionComponent) |
Active → block appears |
| DisappearingWinnerBlock |
isActivated() (via IDetectionComponent) |
Active → block disappears |
| Elevator |
isActivated() (via IDetectionComponent) |
Active → can move |
| MusicBlock |
isActivated() (via IDetectionComponent) |
Active → plays music |
| LaserSolidifier |
isActivated() (via IDetectionComponent) |
Active → places glass blocks |
| LaserReceiver | isActivated() |
Activated by a laser of the correct color |
| RedstoneSensor | isPowered() |
Powered by redstone |
| Lock | isOpened() |
Opened (global state, set when any player with all keys clicks it) |
| BurnableBlock | !isMelted() |
Active while visible (!melted); inactive once melted (invisible, not destroyed — reset on area reactivation) |
| Bonus | via BonusRegistry
|
Active if at least 1 player has obtained it during the current run |
Excluded
- Concentrator: active state is implicit (side-effect of laser movement each tick, not stored). Too complex for v1.
Technical concerns
-
Schematic ID remapping: Must be solved generically for both
LaserSolidifier.targetSenderIdsand the new target component reference. During paste, old component IDs must be mapped to newly created IDs. -
Bonus per-player state:
Bonushas no global boolean. Definition for this mode: activated if ≥1 player has obtained it this run (queryBonusRegistry). -
Cascade update ordering:
ComponentCounterUpdateService.updateDetectionComponents()iterates in unspecified order. With chains (A → B → C), delay can compound to N ticks. Acknowledged as out of scope.