 8f71dac417
			
		
	
	8f71dac417
	
	
	
		
			
			Co-authored-by: Jouramie <16137441+Jouramie@users.noreply.github.com> Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
		
			
				
	
	
		
			144 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import csv
 | |
| import enum
 | |
| from dataclasses import dataclass, field
 | |
| from functools import reduce
 | |
| from pathlib import Path
 | |
| from typing import Dict, List, Protocol, Union, Set, Optional
 | |
| 
 | |
| from BaseClasses import Item, ItemClassification
 | |
| from .. import data
 | |
| from ..logic.logic_event import all_events
 | |
| 
 | |
| ITEM_CODE_OFFSET = 717000
 | |
| 
 | |
| world_folder = Path(__file__).parent
 | |
| 
 | |
| 
 | |
| class Group(enum.Enum):
 | |
|     RESOURCE_PACK = enum.auto()
 | |
|     FRIENDSHIP_PACK = enum.auto()
 | |
|     COMMUNITY_REWARD = enum.auto()
 | |
|     TRASH = enum.auto()
 | |
|     FOOTWEAR = enum.auto()
 | |
|     HATS = enum.auto()
 | |
|     RING = enum.auto()
 | |
|     WEAPON = enum.auto()
 | |
|     WEAPON_GENERIC = enum.auto()
 | |
|     WEAPON_SWORD = enum.auto()
 | |
|     WEAPON_CLUB = enum.auto()
 | |
|     WEAPON_DAGGER = enum.auto()
 | |
|     WEAPON_SLINGSHOT = enum.auto()
 | |
|     PROGRESSIVE_TOOLS = enum.auto()
 | |
|     SKILL_LEVEL_UP = enum.auto()
 | |
|     SKILL_MASTERY = enum.auto()
 | |
|     BUILDING = enum.auto()
 | |
|     WIZARD_BUILDING = enum.auto()
 | |
|     ARCADE_MACHINE_BUFFS = enum.auto()
 | |
|     BASE_RESOURCE = enum.auto()
 | |
|     WARP_TOTEM = enum.auto()
 | |
|     GEODE = enum.auto()
 | |
|     ORE = enum.auto()
 | |
|     FERTILIZER = enum.auto()
 | |
|     SEED = enum.auto()
 | |
|     CROPSANITY = enum.auto()
 | |
|     FISHING_RESOURCE = enum.auto()
 | |
|     SEASON = enum.auto()
 | |
|     TRAVELING_MERCHANT_DAY = enum.auto()
 | |
|     MUSEUM = enum.auto()
 | |
|     FRIENDSANITY = enum.auto()
 | |
|     FESTIVAL = enum.auto()
 | |
|     RARECROW = enum.auto()
 | |
|     TRAP = enum.auto()
 | |
|     BONUS = enum.auto()
 | |
|     MAXIMUM_ONE = enum.auto()
 | |
|     AT_LEAST_TWO = enum.auto()
 | |
|     DEPRECATED = enum.auto()
 | |
|     RESOURCE_PACK_USEFUL = enum.auto()
 | |
|     SPECIAL_ORDER_BOARD = enum.auto()
 | |
|     SPECIAL_ORDER_QI = enum.auto()
 | |
|     BABY = enum.auto()
 | |
|     GINGER_ISLAND = enum.auto()
 | |
|     WALNUT_PURCHASE = enum.auto()
 | |
|     TV_CHANNEL = enum.auto()
 | |
|     QI_CRAFTING_RECIPE = enum.auto()
 | |
|     CHEFSANITY = enum.auto()
 | |
|     CHEFSANITY_STARTER = enum.auto()
 | |
|     CHEFSANITY_QOS = enum.auto()
 | |
|     CHEFSANITY_PURCHASE = enum.auto()
 | |
|     CHEFSANITY_FRIENDSHIP = enum.auto()
 | |
|     CHEFSANITY_SKILL = enum.auto()
 | |
|     CRAFTSANITY = enum.auto()
 | |
|     BOOK_POWER = enum.auto()
 | |
|     LOST_BOOK = enum.auto()
 | |
|     PLAYER_BUFF = enum.auto()
 | |
|     # Mods
 | |
|     MAGIC_SPELL = enum.auto()
 | |
|     MOD_WARP = enum.auto()
 | |
| 
 | |
| 
 | |
| @dataclass(frozen=True)
 | |
| class ItemData:
 | |
|     code_without_offset: Optional[int]
 | |
|     name: str
 | |
|     classification: ItemClassification
 | |
|     mod_name: Optional[str] = None
 | |
|     groups: Set[Group] = field(default_factory=frozenset)
 | |
| 
 | |
|     def __post_init__(self):
 | |
|         if not isinstance(self.groups, frozenset):
 | |
|             super().__setattr__("groups", frozenset(self.groups))
 | |
| 
 | |
|     @property
 | |
|     def code(self):
 | |
|         return ITEM_CODE_OFFSET + self.code_without_offset if self.code_without_offset is not None else None
 | |
| 
 | |
|     def has_any_group(self, *group: Group) -> bool:
 | |
|         groups = set(group)
 | |
|         return bool(groups.intersection(self.groups))
 | |
| 
 | |
| 
 | |
| class StardewItemFactory(Protocol):
 | |
|     def __call__(self, name: Union[str, ItemData], override_classification: ItemClassification = None) -> Item:
 | |
|         raise NotImplementedError
 | |
| 
 | |
| 
 | |
| def load_item_csv():
 | |
|     from importlib.resources import files
 | |
| 
 | |
|     items = []
 | |
|     with files(data).joinpath("items.csv").open() as file:
 | |
|         item_reader = csv.DictReader(file)
 | |
|         for item in item_reader:
 | |
|             id = int(item["id"]) if item["id"] else None
 | |
|             classification = reduce((lambda a, b: a | b), {ItemClassification[str_classification] for str_classification in item["classification"].split(",")})
 | |
|             groups = {Group[group] for group in item["groups"].split(",") if group}
 | |
|             mod_name = str(item["mod_name"]) if item["mod_name"] else None
 | |
|             items.append(ItemData(id, item["name"], classification, mod_name, groups))
 | |
|     return items
 | |
| 
 | |
| 
 | |
| events = [
 | |
|     ItemData(None, e, ItemClassification.progression)
 | |
|     for e in sorted(all_events)
 | |
| ]
 | |
| 
 | |
| all_items: List[ItemData] = load_item_csv() + events
 | |
| item_table: Dict[str, ItemData] = {}
 | |
| items_by_group: Dict[Group, List[ItemData]] = {}
 | |
| 
 | |
| 
 | |
| def initialize_groups():
 | |
|     for item in all_items:
 | |
|         for group in item.groups:
 | |
|             item_group = items_by_group.get(group, list())
 | |
|             item_group.append(item)
 | |
|             items_by_group[group] = item_group
 | |
| 
 | |
| 
 | |
| def initialize_item_table():
 | |
|     item_table.update({item.name: item for item in all_items})
 | |
| 
 | |
| 
 | |
| initialize_item_table()
 | |
| initialize_groups()
 |