Skip to content

feat: bolt.contrib.resource_generator #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions bolt/contrib/resource_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from dataclasses import dataclass, replace
from functools import cache
from typing import Self

from beet import Context, Generator

from bolt import Runtime


@dataclass
class ResourceGenerator:
"""Helpful sugar for generating resource locations and paths

Adds some python data model functions to provide easier access to
:class:`~beet.Generator` functions.

- `__truediv__` lets you define paths similar to :class:`~pathlib.Path`
- `__getattr__` lets you define namespaced paths easily
- `__neg__` makes it cleaner to convert a :class:`ResourceGenerator` into a string

```py
pack = ctx.inject(ResourceGenerator)
function (pack / "load"):
say "Loaded"

pack.entity == "namespace.entity"

tick = pack / "tick"

function_tag minecraft:tick {
"values": [-(tick)] # unfortuntely need parens here
}

function tick:
as @r say hi
```
"""

_generator: Generator

def __init__(self, _generator: Generator | Context):
match _generator:
case Generator():
self._generator = _generator
case Context():
self._generator = _generator.generate

def __truediv__(self, path: str):
"""Allows you to define subpaths based on the root generator"""
return replace(self, _generator=self._generator[path])

@cache
def __getattr__(self, key: str):
"""Produce a namespaced id"""
return self.__getitem__(key)

@cache
def __getitem__(self, key: str):
"""Produce a namespaced id"""
return self._generator.id(key)

def __neg__(self):
"""Simplfied sugar for `__str__`"""
return str(self)

def __str__(self):
return self._generator.format("{namespace}:{path}")[:-1]

def __eq__(self, other: Self):
return str(self) == str(other)

def __repr__(self):
return f"{self.__class__.__name__}({self})"

def __hash__(self):
return hash(str(self))


def beet_default(ctx: Context):
"""Adds `ctx.inject(ResourceGenerator)` as `pack` to runtime globals"""
runtime = ctx.inject(Runtime)
runtime.globals["pack"] = ctx.inject(ResourceGenerator)
15 changes: 15 additions & 0 deletions examples/bolt_resource_generator/beet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
id: demo
require:
- bolt
- bolt.contrib.resource_generator

data_pack:
load: "src"

pipeline:
- mecha

meta:
bolt:
entrypoint:
- "*"
16 changes: 16 additions & 0 deletions examples/bolt_resource_generator/src/data/demo/modules/foo.bolt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
function (pack / "load"):
say hello

tick = pack / "tick"

function_tag minecraft:tick {
"values": [
(-tick)
]
}

function tick:
say tick

as @e[tag=pack.entity]
say entity
41 changes: 41 additions & 0 deletions tests/snapshots/examples__build_bolt_resource_generator__0.pack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Lectern snapshot

## Data pack

`@data_pack pack.mcmeta`

```json
{
"pack": {
"pack_format": 10,
"description": ""
}
}
```

### demo

`@function demo:load`

```mcfunction
say hello
```

`@function demo:tick`

```mcfunction
say demo:tick
execute as @e[tag=demo.entity] run say entity
```

### minecraft

`@function_tag minecraft:tick`

```json
{
"values": [
"demo:tick"
]
}
```