Skip to content

Commit 5329696

Browse files
Implement Activation Phase 2 semantics (Option B)
1 parent 4ee94c2 commit 5329696

File tree

4 files changed

+104
-7
lines changed

4 files changed

+104
-7
lines changed

src/main/java/io/github/legendaryforge/legendary/core/api/activation/ActivationAttemptResult.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,32 @@ public record ActivationAttemptResult(
88
ActivationAttemptStatus status,
99
ActivationDecision decision,
1010
Optional<UUID> sessionId,
11-
Optional<EncounterInstance> instance) {}
11+
Optional<EncounterInstance> instance) {
12+
13+
public ActivationAttemptResult {
14+
if (status == null) throw new NullPointerException("status");
15+
if (decision == null) throw new NullPointerException("decision");
16+
if (sessionId == null) throw new NullPointerException("sessionId");
17+
if (instance == null) throw new NullPointerException("instance");
18+
19+
// SUCCESS => allowed==true and sessionId present (session began)
20+
if (status == ActivationAttemptStatus.SUCCESS) {
21+
if (!decision.allowed()) {
22+
throw new IllegalArgumentException("SUCCESS requires decision.allowed == true");
23+
}
24+
if (sessionId.isEmpty()) {
25+
throw new IllegalArgumentException("SUCCESS requires sessionId");
26+
}
27+
}
28+
29+
// FAILED => sessionId absent and allowed==false (denied or fatal mapped to denial)
30+
if (status == ActivationAttemptStatus.FAILED) {
31+
if (sessionId.isPresent()) {
32+
throw new IllegalArgumentException("FAILED must not have sessionId");
33+
}
34+
if (decision.allowed()) {
35+
throw new IllegalArgumentException("FAILED requires decision.allowed == false");
36+
}
37+
}
38+
}
39+
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package io.github.legendaryforge.legendary.core.api.activation;
22

33
public enum ActivationAttemptStatus {
4-
STARTED,
5-
DENIED,
6-
SESSION_REQUIRED,
4+
SUCCESS,
75
FAILED
86
}

src/main/java/io/github/legendaryforge/legendary/core/internal/activation/DefaultActivationService.java

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,89 @@
44
import io.github.legendaryforge.legendary.core.api.activation.ActivationAttemptStatus;
55
import io.github.legendaryforge.legendary.core.api.activation.ActivationDecision;
66
import io.github.legendaryforge.legendary.core.api.activation.ActivationService;
7+
import io.github.legendaryforge.legendary.core.api.activation.session.ActivationSessionBeginResult;
8+
import io.github.legendaryforge.legendary.core.api.activation.session.ActivationSessionBeginStatus;
9+
import io.github.legendaryforge.legendary.core.api.activation.session.ActivationSessionService;
10+
import io.github.legendaryforge.legendary.core.api.encounter.EncounterKey;
11+
import io.github.legendaryforge.legendary.core.api.gate.ConditionGate;
12+
import io.github.legendaryforge.legendary.core.api.gate.GateDecision;
13+
import io.github.legendaryforge.legendary.core.api.gate.GateService;
714
import io.github.legendaryforge.legendary.core.api.id.ResourceId;
15+
import java.util.Map;
16+
import java.util.Objects;
817
import java.util.Optional;
918

1019
public final class DefaultActivationService implements ActivationService {
1120

21+
private final GateService gates;
22+
private final ActivationSessionService sessions;
23+
24+
public DefaultActivationService(GateService gates, ActivationSessionService sessions) {
25+
this.gates = Objects.requireNonNull(gates, "gates");
26+
this.sessions = Objects.requireNonNull(sessions, "sessions");
27+
}
28+
1229
@Override
1330
public ActivationAttemptResult attemptActivation(ActivationAttemptRequest request) {
14-
// Intentionally inert until Phase 1 · Step 3 wiring (authority + gate + session + encounter creation).
31+
Objects.requireNonNull(request, "request");
32+
33+
EncounterKey encounterKey = EncounterKey.of(request.definition(), request.context());
34+
35+
// Phase 2: evaluate activation gate (if present)
36+
ActivationDecision decision = request.activationGateKey()
37+
.map(gateKey -> evaluateGate(gateKey, request, encounterKey))
38+
.orElseGet(ActivationDecision::allow);
39+
40+
if (!decision.allowed()) {
41+
return new ActivationAttemptResult(
42+
ActivationAttemptStatus.FAILED,
43+
decision,
44+
Optional.empty(),
45+
Optional.empty());
46+
}
47+
48+
// Phase 2: begin activation session
49+
ActivationSessionBeginResult begin = sessions.begin(
50+
new ActivationSessionService.ActivationSessionBeginRequest(
51+
request.activatorId(),
52+
encounterKey,
53+
request.definition(),
54+
request.context(),
55+
request.activationGateKey(),
56+
decision.attributes()
57+
)
58+
);
59+
60+
if (begin.status() == ActivationSessionBeginStatus.CREATED || begin.status() == ActivationSessionBeginStatus.EXISTING) {
61+
return new ActivationAttemptResult(
62+
ActivationAttemptStatus.SUCCESS,
63+
decision,
64+
Optional.of(begin.sessionId()),
65+
Optional.empty());
66+
}
67+
68+
// DENIED => FAILED
69+
ActivationDecision denied = ActivationDecision.deny(begin.reasonCode(), decision.attributes());
1570
return new ActivationAttemptResult(
1671
ActivationAttemptStatus.FAILED,
17-
ActivationDecision.deny(ResourceId.of("legendarycore", "not_wired")),
72+
denied,
1873
Optional.empty(),
1974
Optional.empty());
2075
}
76+
77+
private ActivationDecision evaluateGate(ResourceId gateKey, ActivationAttemptRequest request, EncounterKey encounterKey) {
78+
ConditionGate.GateRequest gateRequest = new ConditionGate.GateRequest(
79+
gateKey,
80+
request.activatorId(),
81+
Optional.of(encounterKey),
82+
Optional.empty(),
83+
Optional.empty(),
84+
Map.of()
85+
);
86+
87+
GateDecision gateDecision = gates.evaluate(gateRequest);
88+
return gateDecision.allowed()
89+
? ActivationDecision.allow()
90+
: ActivationDecision.deny(gateDecision.reasonCode(), gateDecision.attributes());
91+
}
2192
}

src/main/java/io/github/legendaryforge/legendary/core/internal/runtime/DefaultCoreRuntime.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public DefaultCoreRuntime(Optional<PlayerDirectory> players, Optional<PartyDirec
121121
ActivationSessionService sessions = new DefaultActivationSessionService();
122122
this.services.register(ActivationSessionService.class, sessions);
123123

124-
ActivationService activations = new DefaultActivationService();
124+
ActivationService activations = new DefaultActivationService(gates, sessions);
125125
this.services.register(ActivationService.class, activations);
126126

127127
bus.subscribe(

0 commit comments

Comments
 (0)