From e1a85e6f7ad1b713e65471b3f2c19848f5c61168 Mon Sep 17 00:00:00 2001 From: henddher Date: Sun, 2 Oct 2022 20:00:24 -0500 Subject: [PATCH] Add NonExistentRecipe for gracefully allow crafting of an unknown recipe. --- .../contrib/game_systems/crafting/crafting.py | 25 ++++++++++++++++--- .../contrib/game_systems/crafting/tests.py | 7 ++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/evennia/contrib/game_systems/crafting/crafting.py b/evennia/contrib/game_systems/crafting/crafting.py index b97be595db..95f0bb09fb 100644 --- a/evennia/contrib/game_systems/crafting/crafting.py +++ b/evennia/contrib/game_systems/crafting/crafting.py @@ -119,6 +119,7 @@ a full example of the components for creating a sword from base components. """ +import functools from copy import copy from evennia.utils.utils import iter_to_str, callables_from_module, inherits_from, make_iter from evennia.commands.cmdset import CmdSet @@ -340,6 +341,21 @@ class CraftingRecipeBase: return craft_result +class NonExistentRecipe(CraftingRecipeBase): + """A recipe that does not exist and never produces anything.""" + allow_craft = True + allow_reuse = True + + def __init__(self, crafter, *inputs, name="", **kwargs): + super().__init__(crafter, *inputs, **kwargs) + self.name = name + + def pre_craft(self, **kwargs): + msg = f"Unknown recipe '{self.name}'" + self.msg(msg) + raise CraftingError(msg) + + class CraftingRecipe(CraftingRecipeBase): """ The CraftRecipe implements the most common form of crafting: Combining (and @@ -927,9 +943,12 @@ def craft(crafter, recipe_name, *inputs, raise_exception=False, **kwargs): RecipeClass = matches[0] if not RecipeClass: - raise KeyError( - f"No recipe in settings.CRAFT_RECIPE_MODULES has a name matching {recipe_name}" - ) + if raise_exception: + raise KeyError( + f"No recipe in settings.CRAFT_RECIPE_MODULES has a name matching {recipe_name}" + ) + else: + RecipeClass = functools.partial(NonExistentRecipe, name=recipe_name) recipe = RecipeClass(crafter, *inputs, **kwargs) return recipe.craft(raise_exception=raise_exception) diff --git a/evennia/contrib/game_systems/crafting/tests.py b/evennia/contrib/game_systems/crafting/tests.py index 9143785c9b..3d9ae68570 100644 --- a/evennia/contrib/game_systems/crafting/tests.py +++ b/evennia/contrib/game_systems/crafting/tests.py @@ -690,3 +690,10 @@ class TestCraftCommand(BaseEvenniaCommandTest): "testrecipe using tool1, tool2", _MockRecipe.error_consumable_missing_message.format(outputs="Result1", missing="cons1"), ) + + def test_craft__unknown_recipe__failure(self): + self.call( + crafting.CmdCraft(), + "nonexistent from cons1, cons2, cons3 using tool1, tool2", + "Unknown recipe 'nonexistent'", + )