fix(combinations): guard null response; reject self-combination at load
- Combinations.tryUse: only write response when non-null and non-blank, preventing NPE/IllegalArgument for effects-only recipes. - CombinationFactory.fromDto: throw WorldLoadException when a == b, since item singletons make a self-combination impossible at runtime. - Tests: +effectsOnlyRecipeAppliesEffectsWithoutProduceOrResponse (CombinationsTest 7→8), +rejectsSelfCombination (CombinationFactoryTest 4→5). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -123,6 +123,20 @@ class CombinationsTest {
|
||||
assertThat(ctx.getPlayer().hasItem("matches")).isTrue(); // not consumed
|
||||
}
|
||||
|
||||
@Test
|
||||
void effectsOnlyRecipeAppliesEffectsWithoutProduceOrResponse() {
|
||||
Combination effectsOnly = new Combination("matches", "shovel",
|
||||
java.util.List.of(), java.util.List.of(), null,
|
||||
java.util.List.of(new Effect(Effect.Type.SET_FLAG, "rite_done")),
|
||||
null, null);
|
||||
GameContext ctx = ctx(effectsOnly);
|
||||
give(ctx, "matches");
|
||||
give(ctx, "shovel");
|
||||
Combinations.tryUse(ctx, "matches", "shovel");
|
||||
assertThat(ctx.getState().isSet("rite_done")).isTrue();
|
||||
assertThat(out(ctx)).doesNotContain("null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void metRequiresAppliesEffectsAndProduces() {
|
||||
Combination gated = new Combination("matches", "torch",
|
||||
|
||||
@@ -58,4 +58,12 @@ class CombinationFactoryTest {
|
||||
.isInstanceOf(WorldLoadException.class)
|
||||
.hasMessageContaining("wraith");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsSelfCombination() {
|
||||
CombinationDto dto = new CombinationDto("torch", "torch", null, null, null, null, "x", null);
|
||||
assertThatThrownBy(() -> CombinationFactory.fromDto(dto, items()))
|
||||
.isInstanceOf(WorldLoadException.class)
|
||||
.hasMessageContaining("itself");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user