Skip to content

Commit c03b42c

Browse files
committed
feat: generate datapack overlays
1 parent dd086fc commit c03b42c

File tree

195 files changed

+2267
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+2267
-3
lines changed

TODO.md

Lines changed: 5 additions & 0 deletions

beet_observer/data_pack.py

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
from typing import Any
2+
3+
from beet import Context, NamespaceProxy
4+
5+
6+
def gen_dp_overlays(ctx: Context, ctx_overlay: Context, overlay_dir: str) -> None:
7+
"""
8+
Generates overlays between two datapacks.
9+
10+
Keyword arguments:</br>
11+
`ctx` -- the build context</br>
12+
`ctx_overlay` -- the overlay context</br>
13+
`overlay_dir` -- the directory of the overlay</br>
14+
"""
15+
# create list of all datapack file types
16+
file_types: list[tuple[NamespaceProxy[Any], NamespaceProxy[Any]]] = [
17+
(ctx.data.advancements, ctx_overlay.data.advancements),
18+
(ctx.data.functions, ctx_overlay.data.functions),
19+
(ctx.data.item_modifiers, ctx_overlay.data.item_modifiers),
20+
(ctx.data.loot_tables, ctx_overlay.data.loot_tables),
21+
(ctx.data.predicates, ctx_overlay.data.predicates),
22+
(ctx.data.recipes, ctx_overlay.data.recipes),
23+
(ctx.data.trim_pattern, ctx_overlay.data.trim_pattern),
24+
(ctx.data.trim_material, ctx_overlay.data.trim_material),
25+
(ctx.data.structures, ctx_overlay.data.structures),
26+
(ctx.data.chat_type, ctx_overlay.data.chat_type),
27+
(ctx.data.damage_type, ctx_overlay.data.damage_type),
28+
(ctx.data.banner_patterns, ctx_overlay.data.banner_patterns),
29+
(ctx.data.wolf_variants, ctx_overlay.data.wolf_variants),
30+
(ctx.data.enchantments, ctx_overlay.data.enchantments),
31+
(ctx.data.enchantment_providers, ctx_overlay.data.enchantment_providers),
32+
(ctx.data.jukebox_songs, ctx_overlay.data.jukebox_songs),
33+
(ctx.data.painting_variants, ctx_overlay.data.painting_variants),
34+
(ctx.data.block_tags, ctx_overlay.data.block_tags),
35+
(ctx.data.entity_type_tags, ctx_overlay.data.entity_type_tags),
36+
(ctx.data.fluid_tags, ctx_overlay.data.fluid_tags),
37+
(ctx.data.function_tags, ctx_overlay.data.function_tags),
38+
(ctx.data.game_event_tags, ctx_overlay.data.game_event_tags),
39+
(ctx.data.item_tags, ctx_overlay.data.item_tags),
40+
(ctx.data.chat_type_tags, ctx_overlay.data.chat_type_tags),
41+
(ctx.data.damage_type_tags, ctx_overlay.data.damage_type_tags),
42+
(ctx.data.banner_pattern_tags, ctx_overlay.data.banner_pattern_tags),
43+
(ctx.data.cat_variant_tags, ctx_overlay.data.cat_variant_tags),
44+
(ctx.data.enchantment_tags, ctx_overlay.data.enchantment_tags),
45+
(ctx.data.instrument_tags, ctx_overlay.data.instrument_tags),
46+
(ctx.data.painting_variant_tags, ctx_overlay.data.painting_variant_tags),
47+
(
48+
ctx.data.point_of_interest_type_tags,
49+
ctx_overlay.data.point_of_interest_type_tags,
50+
),
51+
]
52+
# for each file type, check for required overlays
53+
for registry, registry_overlay in file_types:
54+
check_registry(ctx, ctx_overlay, overlay_dir, registry, registry_overlay)
55+
56+
# get pack.mcmeta overlay entries
57+
mcmeta: dict[str, dict[str, list[dict[str, Any]]]] = ctx.data.mcmeta.data.copy()
58+
if "overlays" not in mcmeta:
59+
mcmeta["overlays"] = {}
60+
if "entries" not in mcmeta["overlays"]:
61+
mcmeta["overlays"]["entries"] = []
62+
entries = mcmeta["overlays"]["entries"]
63+
64+
# add overlays to pack.mcmeta
65+
for overlay in ctx.data.overlays:
66+
# check if it's the top-level overlay
67+
if overlay == ctx.meta["observer"]["default_dir_dp"]:
68+
# delete pack.mcmeta from overlay (requuired for tests)
69+
default_dir = ctx.meta["observer"]["default_dir_dp"]
70+
if ctx.data.overlays[default_dir].mcmeta:
71+
del ctx.data.overlays[default_dir].mcmeta
72+
73+
# get pack format from build context
74+
if "default_format" in ctx.meta["observer"]:
75+
formats = ctx.meta["observer"]["default_format"]
76+
else:
77+
formats = ctx.data.mcmeta.data["pack"]["pack_format"]
78+
else:
79+
# get formats from overlay pack
80+
if "supported_formats" in ctx_overlay.data.mcmeta.data["pack"]:
81+
formats = ctx_overlay.data.mcmeta.data["pack"]["supported_formats"]
82+
else:
83+
formats = ctx_overlay.data.mcmeta.data["pack"]["pack_format"]
84+
85+
# update pack.mcmeta overlay entries
86+
entries.append(
87+
{
88+
"formats": formats,
89+
"directory": overlay,
90+
}
91+
)
92+
93+
# save overlay entries in pack.mcmeta
94+
ctx.data.mcmeta.data.update({"overlays": {"entries": entries}})
95+
96+
97+
def check_registry(
98+
ctx: Context,
99+
ctx_overlay: Context,
100+
overlay_dir: str,
101+
registry: NamespaceProxy[Any],
102+
registry_overlay: NamespaceProxy[Any],
103+
) -> None:
104+
"""
105+
Generates overlays for each namespace proxy.
106+
107+
Keyword arguments:</br>
108+
`ctx` -- the build context</br>
109+
`ctx_overlay` -- the overlay context</br>
110+
`overlay_dir` -- the directory of the overlay</br>
111+
`registry` -- the namespace proxy from the build context</br>
112+
`registry_overlay` -- the namespace proxy from the overlay context</br>
113+
"""
114+
# check each file in the build pack
115+
for name in list(registry):
116+
if name in registry_overlay:
117+
# exists in both, so check if an overlay is needed
118+
gen_registry_overlay(ctx, overlay_dir, name, registry, registry_overlay)
119+
else:
120+
# exists only in overlay, so create a deletion overlay
121+
gen_registry_overlay(
122+
ctx, overlay_dir, name, registry, registry_overlay, "deletion"
123+
)
124+
125+
# for all remaining files (of this type) in the overlay pack, add to build pack as an overlay
126+
for name in list(registry_overlay):
127+
gen_registry_overlay(
128+
ctx, overlay_dir, name, registry, registry_overlay, "addition"
129+
)
130+
131+
132+
def gen_registry_overlay(
133+
ctx: Context,
134+
overlay_dir: str,
135+
name: str,
136+
registry: NamespaceProxy[Any],
137+
registry_overlay: NamespaceProxy[Any],
138+
type: str = "",
139+
) -> None:
140+
"""
141+
Checks if two functions have the same contents and generate an overlay if they don't.
142+
143+
Keyword arguments:</br>
144+
`ctx` -- the build context</br>
145+
`overlay_dir` -- the directory of the generated overlay</br>
146+
`name` -- the name of the file</br>
147+
`registry` -- the namespace proxy from the build context</br>
148+
`registry_overlay` -- the namespace proxy from the overlay context</br>
149+
`type` -- either "deletion" or "addition" (default: `""`)</br>
150+
"""
151+
if type == "deletion":
152+
# move file from build pack to overlay in build pack
153+
default_dir = ctx.meta["observer"]["default_dir_dp"]
154+
ctx.data.overlays[default_dir][name] = registry[name]
155+
del registry[name]
156+
elif type == "addition":
157+
# move function from overlay pack to overlay in build pack
158+
ctx.data.overlays[overlay_dir][name] = registry_overlay[name]
159+
else:
160+
# check if files are exactly the same
161+
if registry[name] != registry_overlay[name]:
162+
# move function from overlay pack to overlay in build pack
163+
ctx.data.overlays[overlay_dir][name] = registry_overlay[name]
164+
165+
# remove file from overlay pack
166+
if name in registry_overlay:
167+
del registry_overlay[name]

beet_observer/plugin.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,44 @@
1-
from beet import Context
1+
from beet import Context, run_beet
2+
3+
from .data_pack import *
4+
from .resource_pack import *
25

36

47
def beet_default(ctx: Context):
5-
return
8+
if "observer" not in ctx.meta:
9+
return
10+
# get default directories
11+
if "default_dir" not in ctx.meta["observer"]:
12+
# default dir not defined
13+
ctx.meta["observer"]["default_dir_dp"] = "default_overlay"
14+
ctx.meta["observer"]["default_dir_rp"] = "default_overlay"
15+
elif isinstance(ctx.meta["observer"]["default_dir"], str):
16+
# default dir is the same for dp and rp
17+
ctx.meta["observer"]["default_dir_dp"] = ctx.meta["observer"]["default_dir"]
18+
ctx.meta["observer"]["default_dir_rp"] = ctx.meta["observer"]["default_dir"]
19+
else:
20+
# default dir is different for dp and rp
21+
ctx.meta["observer"]["default_dir_dp"] = ctx.meta["observer"]["default_dir"][
22+
"dp"
23+
]
24+
ctx.meta["observer"]["default_dir_rp"] = ctx.meta["observer"]["default_dir"][
25+
"rp"
26+
]
27+
# loop through all overlays
28+
for overlay in ctx.meta["observer"]["overlays"]:
29+
# create relative path
30+
path = f"{ctx.directory}/{overlay['process']}"
31+
# generate context for overlay pack
32+
with run_beet(
33+
config={"data_pack": {"load": "."}, "resource_pack": {"load": "."}},
34+
directory=path,
35+
) as ctx_overlay:
36+
if "directory" not in overlay:
37+
dp_dir = f"overlay_{ctx_overlay.data.pack_format}"
38+
rp_dir = f"overlay_{ctx_overlay.assets.pack_format}"
39+
else:
40+
dp_dir = overlay["directory"]
41+
rp_dir = overlay["directory"]
42+
# compare build pack and overlay pack
43+
gen_dp_overlays(ctx, ctx_overlay, dp_dir)
44+
gen_rp_overlays(ctx, ctx_overlay, rp_dir)

beet_observer/resource_pack.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from beet import Context
2+
3+
4+
def gen_rp_overlays(ctx: Context, ctx_overlay: Context, directory: str):
5+
return

examples/nested_overlay1/beet.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
data_pack:
2+
load: src
3+
pack_format: 57
4+
supported_formats: [48,57]
5+
6+
pipeline:
7+
- beet_observer
8+
9+
meta:
10+
observer:
11+
overlays:
12+
- process: nested/proc
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
say an overlay is created for this
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
say this is the same in both
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"pack": {
3+
"pack_format": 48,
4+
"description": ""
5+
}
6+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
say this remains in the normal data folder
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
say this is the same in both

0 commit comments

Comments
 (0)