diff --git a/doc/src/common/state.py b/doc/src/common/state.py index 4a1d7ca1..645d6b12 100644 --- a/doc/src/common/state.py +++ b/doc/src/common/state.py @@ -1,19 +1,8 @@ from __future__ import annotations -from dataclasses import dataclass -from itertools import chain +from dataclasses import dataclass, field from pathlib import Path -from typing import ( - Any, - ClassVar, - Collection, - Generic, - Iterable, - Mapping, - Self, - Type, - TypeVar, -) +from typing import Any, ClassVar, Generic, Self, Type, TypeVar from common.deserialize import ( TypedConfig, @@ -161,17 +150,15 @@ class StatefulInternallyTaggedUnion( } -StatefulUnions = Mapping[ - Type[StatefulInternallyTaggedUnion[AnyState]], - Collection[Type[StatefulInternallyTaggedUnion[AnyState]]], -] +@dataclass(kw_only=True) +class TypeTaggedUnion(StatefulInternallyTaggedUnion[AnyState], tag="type", value=None): + type: ResourceLocation = field(init=False) + def __init_subclass__(cls, type: str | None) -> None: + super().__init_subclass__("type", type) + if type is not None: + cls.type = ResourceLocation.from_str(type) -def make_stateful_union_hooks( - base: Type[StatefulInternallyTaggedUnion[AnyState]], - subtypes: Iterable[Type[StatefulInternallyTaggedUnion[AnyState]]], - state: AnyState, -) -> TypeHooks[StatefulInternallyTaggedUnion[AnyState]]: - return { - subtype: subtype.make_type_hook(state) for subtype in chain([base], subtypes) - } + @property + def _tag_value(self) -> str: + return str(self.type) diff --git a/doc/src/minecraft/recipe/abstract.py b/doc/src/minecraft/recipe/abstract.py index b33b5717..a511d9c9 100644 --- a/doc/src/minecraft/recipe/abstract.py +++ b/doc/src/minecraft/recipe/abstract.py @@ -1,49 +1,36 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Any, Self, TypeVar +from dataclasses import dataclass +from typing import Any, Self from common.deserialize import TypeHook, load_json_data -from common.state import BookState, StatefulInternallyTaggedUnion +from common.state import AnyState, TypeTaggedUnion from minecraft.resource import ResourceLocation -_T_State = TypeVar("_T_State", bound=BookState) - @dataclass(kw_only=True) -class Recipe(StatefulInternallyTaggedUnion[_T_State], tag="type", value=None): +class Recipe(TypeTaggedUnion[AnyState], type=None): id: ResourceLocation - - type: ResourceLocation = field(init=False) group: str | None = None - def __init_subclass__(cls, type: str) -> None: - super().__init_subclass__(__class__._tag_key, type) - cls.type = ResourceLocation.from_str(type) - @classmethod - def make_type_hook(cls, state: BookState) -> TypeHook[Self]: + def make_type_hook(cls, state: AnyState) -> TypeHook[Self]: """Creates a type hook which, given a stringified ResourceLocation, loads and returns the recipe json at that location.""" + super_hook = super().make_type_hook(state) - def type_hook(raw_id: str | Any) -> Self | dict[str, Any]: - # FIXME: this should use isinstance_or_raise but I'm probably redoing it - if isinstance(raw_id, cls): - return raw_id + def type_hook(data: str | Any) -> Self | dict[str, Any]: + if isinstance(data, str): + # FIXME: hack + # the point of this is to ensure the recipe exists on all platforms + # because we've had issues with that in the past, eg. in Hexal + id = ResourceLocation.from_str(data) + data = {} + for recipe_dir in state.props.recipe_dirs: + # TODO: should this use id.namespace somewhere? + path = recipe_dir / f"{id.path}.json" + data = load_json_data(cls, path, {"id": id}) - # FIXME: hack - # the point of this is to ensure the recipe exists on all platforms - # because we've had issues with that in the past, eg. in Hexal - id = ResourceLocation.from_str(raw_id) - data: dict[str, Any] = {} - for recipe_dir in state.props.recipe_dirs: - # TODO: should this use id.namespace somewhere? - data = load_json_data(cls, recipe_dir / f"{id.path}.json") - - return data | {"id": id, "state": state} + return super_hook(data) return type_hook - - @property - def _tag_value(self) -> str: - return str(self.type) diff --git a/doc/src/patchouli/page/abstract.py b/doc/src/patchouli/page/abstract.py index a1448211..7c795d82 100644 --- a/doc/src/patchouli/page/abstract.py +++ b/doc/src/patchouli/page/abstract.py @@ -4,29 +4,23 @@ from typing import Any, Self from common.deserialize import TypeHook, rename from common.formatting import FormatTree -from common.state import AnyState, StatefulInternallyTaggedUnion +from common.state import AnyState, TypeTaggedUnion from common.types import LocalizedStr from minecraft.recipe.concrete import CraftingRecipe from minecraft.resource import ResourceLocation @dataclass(kw_only=True) -class Page(StatefulInternallyTaggedUnion[AnyState], tag="type", value=None): +class Page(TypeTaggedUnion[AnyState], type=None): """Base class for Patchouli page types. See: https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/page-types """ - type: ResourceLocation = field(init=False) advancement: ResourceLocation | None = None flag: str | None = None anchor: str | None = None - def __init_subclass__(cls, type: str | None) -> None: - super().__init_subclass__("type", type) - if type is not None: - cls.type = ResourceLocation.from_str(type) - @classmethod def make_type_hook(cls, state: AnyState) -> TypeHook[Self]: super_hook = super().make_type_hook(state) @@ -39,10 +33,6 @@ class Page(StatefulInternallyTaggedUnion[AnyState], tag="type", value=None): return type_hook - @property - def _tag_value(self) -> str: - return str(self.type) - @dataclass(kw_only=True) class PageWithText(Page[AnyState], type=None):