33from collections import defaultdict
44from typing import TYPE_CHECKING
55
6- from beet import Context , Function , LootTable , Predicate
6+ from beet import Context , Function , LootTable , PackFile , Predicate
77
8- from bookshelf .definitions import MC_VERSIONS
98from bookshelf .models import Block , StateNode , StatePredicate , StateProperty , StateValue
109from bookshelf .services import minecraft
1110
1211if TYPE_CHECKING :
13- from collections .abc import Sequence
14-
12+ from collections .abc import Iterable , Sequence
1513
1614ATTR_TAGS = [
1715 ("has_state" , lambda b : b .group > 0 ),
5048 "sounds" ,
5149}
5250
51+ LOOT_TABLE_INCLUDE = {
52+ "type" ,
53+ "item" ,
54+ "group" ,
55+ "sounds" , # @deprecated sounds (removed in in 4.0.0)
56+ }
57+
5358
54- def beet_default (ctx : Context ) -> None :
55- """Generate files used by the bs.block module."""
56- namespace = ctx .directory .name
57- blocks = minecraft .get_blocks (ctx .cache , MC_VERSIONS [- 1 ])
59+ @minecraft .generator
60+ def beet_default (ctx : Context , version : str ) -> Iterable [tuple [str , PackFile ]]:
61+ """Generate files used by the module for a given version."""
62+ print (f"run { version } " )
63+ ns = ctx .directory .name
64+ blocks = minecraft .get_blocks (ctx .cache , version )
5865
59- loot_table = make_block_loot_table (blocks )
60- ctx .generate (f"{ namespace } :internal/get_type" , render = loot_table )
61- loot_table = make_block_loot_table (blocks , f"{ namespace } :internal" )
62- ctx .generate (f"{ namespace } :internal/get_block" , render = loot_table )
66+ yield f"{ ns } :internal/get_type" , make_block_loot_table (blocks )
67+ yield f"{ ns } :internal/get_block" , make_block_loot_table (blocks , f"{ ns } :internal" )
6368
6469 for state in {s .group : s for b in blocks for s in b .properties }.values ():
65- loot_table = make_block_state_loot_table ( state , f"{ namespace } :internal" )
66- ctx . generate ( f"{ namespace } :internal/group_ { state . group } " , render = loot_table )
70+ location = f"{ ns } :internal/group_ { state . group } "
71+ yield location , make_block_state_loot_table ( state , f"{ ns } :internal" )
6772
6873 for name , formatter in [
6974 ("types" , format_types_table ),
7075 ("items" , format_items_table ),
7176 ("groups" , format_groups_table ),
7277 ]:
73- ctx .generate (
74- f"{ namespace } :import/{ name } _table" ,
75- render = Function (source_path = f"{ name } _table.jinja" ),
76- data = formatter (blocks ),
77- )
78+ location = f"{ ns } :import/{ name } _table"
79+ content = ctx .template .render (f"{ name } _table.jinja" , data = formatter (blocks ))
80+ yield location , Function (content )
7881
7982 for name , predicate in ATTR_TAGS :
80- tag = ctx .data .block_tags [f"{ namespace } :{ name } " ]
81- minecraft .update_block_tag ( tag , blocks , predicate )
83+ base = ctx .data .block_tags [location := f"{ ns } :{ name } " ]
84+ yield location , minecraft .make_block_tag ( base , blocks , predicate )
8285
8386 for name , attribute in ATTR_PREDICATES :
8487 groups = defaultdict (list )
8588 for block in blocks :
8689 groups [attribute (block )].append (block )
87- merge_attr_predicate (ctx .data .predicates [f"{ namespace } :{ name } " ], groups )
90+
91+ base = ctx .data .predicates [location := f"{ ns } :{ name } " ]
92+ yield location , make_attr_predicate (base , groups )
8893
8994 for name , attribute in ATTR_LOOT_TABLES :
9095 seen = set ()
@@ -93,11 +98,11 @@ def beet_default(ctx: Context) -> None:
9398 groups [value := attribute (block )].append (block )
9499 if isinstance (value , StatePredicate ) and value not in seen :
95100 seen .add (value )
96- file = make_attr_state_loot_table ( name , value )
97- ctx . generate ( f" { namespace } :internal/ { name } _ { value . group } " , render = file )
101+ location = f" { ns } :internal/ { name } _ { value . group } "
102+ yield location , make_attr_state_loot_table ( name , value )
98103
99- file = make_attr_loot_table ( name , groups , f"{ namespace } :internal" )
100- ctx . generate ( f"{ namespace } :internal/get_ { name } " , render = file )
104+ location = f"{ ns } :internal/get_ { name } "
105+ yield location , make_attr_loot_table ( name , groups , f"{ ns } :internal" )
101106
102107
103108def format_types_table (blocks : Sequence [Block ]) -> dict :
@@ -126,11 +131,10 @@ def format_groups_table(blocks: Sequence[Block]) -> dict:
126131
127132def format_block_loot_entry (entry : dict , block : Block ) -> dict :
128133 """Attach block data to a loot entry."""
129- # @deprecated sounds (removed in in 4.0.0)
130134 return {** entry , "functions" : [{
131135 "function" : "set_custom_data" ,
132136 "tag" : minecraft .render_snbt (block .model_dump (
133- include = { "type" , "item" , "group" , "sounds" } ,
137+ include = LOOT_TABLE_INCLUDE ,
134138 )),
135139 }]}
136140
@@ -225,10 +229,10 @@ def make_attr_state_loot_table(attr: str, entry: StatePredicate) -> LootTable:
225229 })
226230
227231
228- def merge_attr_predicate (
229- predicate : Predicate ,
232+ def make_attr_predicate (
233+ base : Predicate ,
230234 groups : dict [StateValue [bool ], list [Block ]],
231- ) -> None :
235+ ) -> Predicate :
232236 """Create a predicate for a collection of blocks grouped by attribute."""
233237 def optimize_entry (entry : dict ) -> dict | None :
234238 terms = list (filter (None , entry .get ("terms" , [])))
@@ -257,8 +261,8 @@ def build_node[T: bool](node: StateNode[T] | T) -> dict | None:
257261
258262 return optimize_entry ({"condition" :"any_of" ,"terms" :terms })
259263
260- predicate . set_content ( optimize_entry ({
261- ** predicate .data ,
264+ return Predicate ({
265+ ** base .data ,
262266 "condition" : "any_of" ,
263267 "terms" : [optimize_entry ({
264268 "condition" : "all_of" , "terms" :[{
@@ -269,4 +273,4 @@ def build_node[T: bool](node: StateNode[T] | T) -> dict | None:
269273 "condition" : "location_check" ,
270274 "predicate" : {"block" : {"blocks" : [b .type [10 :] for b in blocks ]}},
271275 } for group , blocks in groups .items () if group ],
272- }))
276+ })
0 commit comments