Skip to content

Commit

Permalink
feat: add lectern.contrib.vanilla
Browse files Browse the repository at this point in the history
  • Loading branch information
vberlier committed Dec 2, 2023
1 parent a82e2de commit c21e95d
Show file tree
Hide file tree
Showing 8 changed files with 302 additions and 78 deletions.
1 change: 1 addition & 0 deletions examples/with_vanilla/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
out/
46 changes: 46 additions & 0 deletions examples/with_vanilla/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Load vanilla resources

## Basics

The `lectern.contrib.vanilla` plugin can copy resources from the vanilla data pack and resource pack.

`@vanilla assets/minecraft/lang/en_us.json`

The directive can select multiple files at once.

`@vanilla data/minecraft/tags/items/anvil.json assets/minecraft/blockstates/anvil.json`

It's possible to specify a destination ending in `:` before the file pattern. If the pattern refers to multiple files, the destination must be a directory.

`@vanilla assets/foo/lang/dummy.json: assets/minecraft/lang/en_us.json`

File patterns are regular expressions, they can match multiple files at once.

`@vanilla assets/minecraft/lang/fr_.*`

> [!WARNING]
> Beet statically analyzes every pattern to only mount the necessary vanilla resources before matching the regex. Very generic patterns like `@vanilla data/minecraft/.*json` will be slower to execute as the static base path doesn't help much with reducing the set of files to scan.
The destination can contain references to capture groups in the pattern.

`@vanilla assets/foo/models/\1: assets/minecraft/models/(block|item)/.+_sapling.json`

## Load by resource location

The plugin also registers directives similar to `@vanilla` but that work with a specific resource type and let you specify patterns as resource locations instead of having to write out the complete file path.

`@vanilla_texture minecraft:block/stone`

Instead of regular expressions, these resource location patterns only support gitignore-like matching syntax.

`@vanilla_worldgen_noise minecraft:aquifer* minecraft:noodle`

The directives still support mounting the resource to a different destination. The destination must be a resource location too.

`@vanilla_structure foo:better_igloo: minecraft:igloo/*`

## Override minecraft version

All directives default to loading files from the minecraft version configured in the current project. You con override that by specifying the version as a modifier between parentheses right after the name of the directive.

`@vanilla(1.18.2) assets/foo/lang/old_us.json: assets/minecraft/lang/en_us.json`
8 changes: 8 additions & 0 deletions examples/with_vanilla/beet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require:
- lectern.contrib.vanilla
output: "out"
pipeline:
- lectern
meta:
lectern:
load: README.md
2 changes: 1 addition & 1 deletion lectern/contrib/messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from typing import Literal, Optional

from beet import Context, ErrorMessage, Function, ListOption, configurable
from pydantic import BaseModel
from pydantic.v1 import BaseModel

from lectern import Document, LinkFragmentLoader

Expand Down
76 changes: 76 additions & 0 deletions lectern/contrib/vanilla.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
__all__ = [
"VanillaFilesDirective",
"VanillaMatchDirective",
]


from dataclasses import dataclass
from typing import Union

from beet import Context, DataPack, PackQuery, ResourcePack
from beet.contrib.vanilla import Vanilla

from lectern import Document, Fragment, InvalidFragment


def beet_default(ctx: Context):
vanilla = ctx.inject(Vanilla)
document = ctx.inject(Document)
document.directives["vanilla"] = VanillaFilesDirective(vanilla, ctx.query)
for file_type in ctx.get_file_types():
document.directives[f"vanilla_{file_type.snake_name}"] = VanillaMatchDirective(
file_type.snake_name, vanilla, ctx.query
)


@dataclass
class VanillaFilesDirective:
vanilla: Vanilla
query: PackQuery[Union[ResourcePack, DataPack]]

def __call__(self, fragment: Fragment, assets: ResourcePack, data: DataPack):
release = self.vanilla.releases[
fragment.modifier or self.vanilla.minecraft_version
]

if not fragment.arguments:
raise InvalidFragment(
"Missing arguments for directive @vanilla.", fragment.start_line
)

head, *tail = fragment.arguments

client_jar = release.client_jar
query = self.query.from_pack(client_jar.assets, client_jar.data).prepare(
files={head[:-1]: tail} if head.endswith(":") else fragment.arguments
)

for base_path in query.analyze_base_paths():
release.mount(base_path, fetch_objects=True)

query.copy_to(assets, data)


@dataclass
class VanillaMatchDirective:
group: str
vanilla: Vanilla
query: PackQuery[Union[ResourcePack, DataPack]]

def __call__(self, fragment: Fragment, assets: ResourcePack, data: DataPack):
release = self.vanilla.releases[
fragment.modifier or self.vanilla.minecraft_version
]

args = fragment.arguments or ["*"]
head, *tail = args

client_jar = release.client_jar
query = self.query.from_pack(client_jar.assets, client_jar.data).prepare(
match={self.group: {head[:-1]: tail} if head.endswith(":") else args}
)

for base_path in query.analyze_base_paths():
release.mount(base_path, fetch_objects=True)

query.copy_to(assets, data)
2 changes: 1 addition & 1 deletion lectern/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing import List, Literal, Optional

from beet import Context, ListOption, PackageablePath, configurable
from pydantic import BaseModel
from pydantic.v1 import BaseModel

from .document import Document
from .loaders import LinkFragmentLoader
Expand Down
Loading

0 comments on commit c21e95d

Please sign in to comment.