Fix Recipe impl and create TypeTaggedUnion

This commit is contained in:
object-Object 2023-06-25 17:22:35 -04:00
parent a6cfb0e244
commit 8414154460
3 changed files with 32 additions and 68 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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):