Fix Recipe impl and create TypeTaggedUnion
This commit is contained in:
parent
a6cfb0e244
commit
8414154460
3 changed files with 32 additions and 68 deletions
|
@ -1,19 +1,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
from itertools import chain
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import (
|
from typing import Any, ClassVar, Generic, Self, Type, TypeVar
|
||||||
Any,
|
|
||||||
ClassVar,
|
|
||||||
Collection,
|
|
||||||
Generic,
|
|
||||||
Iterable,
|
|
||||||
Mapping,
|
|
||||||
Self,
|
|
||||||
Type,
|
|
||||||
TypeVar,
|
|
||||||
)
|
|
||||||
|
|
||||||
from common.deserialize import (
|
from common.deserialize import (
|
||||||
TypedConfig,
|
TypedConfig,
|
||||||
|
@ -161,17 +150,15 @@ class StatefulInternallyTaggedUnion(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StatefulUnions = Mapping[
|
@dataclass(kw_only=True)
|
||||||
Type[StatefulInternallyTaggedUnion[AnyState]],
|
class TypeTaggedUnion(StatefulInternallyTaggedUnion[AnyState], tag="type", value=None):
|
||||||
Collection[Type[StatefulInternallyTaggedUnion[AnyState]]],
|
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(
|
@property
|
||||||
base: Type[StatefulInternallyTaggedUnion[AnyState]],
|
def _tag_value(self) -> str:
|
||||||
subtypes: Iterable[Type[StatefulInternallyTaggedUnion[AnyState]]],
|
return str(self.type)
|
||||||
state: AnyState,
|
|
||||||
) -> TypeHooks[StatefulInternallyTaggedUnion[AnyState]]:
|
|
||||||
return {
|
|
||||||
subtype: subtype.make_type_hook(state) for subtype in chain([base], subtypes)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,49 +1,36 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from typing import Any, Self, TypeVar
|
from typing import Any, Self
|
||||||
|
|
||||||
from common.deserialize import TypeHook, load_json_data
|
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
|
from minecraft.resource import ResourceLocation
|
||||||
|
|
||||||
_T_State = TypeVar("_T_State", bound=BookState)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class Recipe(StatefulInternallyTaggedUnion[_T_State], tag="type", value=None):
|
class Recipe(TypeTaggedUnion[AnyState], type=None):
|
||||||
id: ResourceLocation
|
id: ResourceLocation
|
||||||
|
|
||||||
type: ResourceLocation = field(init=False)
|
|
||||||
group: str | None = None
|
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
|
@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
|
"""Creates a type hook which, given a stringified ResourceLocation, loads and
|
||||||
returns the recipe json at that location."""
|
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]:
|
def type_hook(data: str | Any) -> Self | dict[str, Any]:
|
||||||
# FIXME: this should use isinstance_or_raise but I'm probably redoing it
|
if isinstance(data, str):
|
||||||
if isinstance(raw_id, cls):
|
# FIXME: hack
|
||||||
return raw_id
|
# 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
|
return super_hook(data)
|
||||||
# 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 type_hook
|
return type_hook
|
||||||
|
|
||||||
@property
|
|
||||||
def _tag_value(self) -> str:
|
|
||||||
return str(self.type)
|
|
||||||
|
|
|
@ -4,29 +4,23 @@ from typing import Any, Self
|
||||||
|
|
||||||
from common.deserialize import TypeHook, rename
|
from common.deserialize import TypeHook, rename
|
||||||
from common.formatting import FormatTree
|
from common.formatting import FormatTree
|
||||||
from common.state import AnyState, StatefulInternallyTaggedUnion
|
from common.state import AnyState, TypeTaggedUnion
|
||||||
from common.types import LocalizedStr
|
from common.types import LocalizedStr
|
||||||
from minecraft.recipe.concrete import CraftingRecipe
|
from minecraft.recipe.concrete import CraftingRecipe
|
||||||
from minecraft.resource import ResourceLocation
|
from minecraft.resource import ResourceLocation
|
||||||
|
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class Page(StatefulInternallyTaggedUnion[AnyState], tag="type", value=None):
|
class Page(TypeTaggedUnion[AnyState], type=None):
|
||||||
"""Base class for Patchouli page types.
|
"""Base class for Patchouli page types.
|
||||||
|
|
||||||
See: https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/page-types
|
See: https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/page-types
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type: ResourceLocation = field(init=False)
|
|
||||||
advancement: ResourceLocation | None = None
|
advancement: ResourceLocation | None = None
|
||||||
flag: str | None = None
|
flag: str | None = None
|
||||||
anchor: 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
|
@classmethod
|
||||||
def make_type_hook(cls, state: AnyState) -> TypeHook[Self]:
|
def make_type_hook(cls, state: AnyState) -> TypeHook[Self]:
|
||||||
super_hook = super().make_type_hook(state)
|
super_hook = super().make_type_hook(state)
|
||||||
|
@ -39,10 +33,6 @@ class Page(StatefulInternallyTaggedUnion[AnyState], tag="type", value=None):
|
||||||
|
|
||||||
return type_hook
|
return type_hook
|
||||||
|
|
||||||
@property
|
|
||||||
def _tag_value(self) -> str:
|
|
||||||
return str(self.type)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class PageWithText(Page[AnyState], type=None):
|
class PageWithText(Page[AnyState], type=None):
|
||||||
|
|
Loading…
Reference in a new issue