flaremc 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flaremc-0.2.4/PKG-INFO +82 -0
- flaremc-0.2.4/README.md +71 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/__init__.py +6 -4
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/cli.py +8 -1
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/command_parser.py +2 -2
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/compiler.py +20 -20
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/context.py +99 -34
- flaremc-0.2.4/flare/control_flow.py +276 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/execute_modifiers.py +12 -12
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/preprocessor.py +54 -7
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/validator/matchers.py +35 -2
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/validator/schema.py +9 -1
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/variables/__init__.py +1 -1
- flaremc-0.2.4/flare/variables/bigscore.py +492 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/variables/complex.py +17 -51
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/variables/core.py +83 -2
- flaremc-0.2.4/flare/variables/float32.py +380 -0
- flaremc-0.2.4/flare/variables/float64.py +314 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/variables/nbt.py +249 -194
- flaremc-0.2.4/flare/variables/score.py +580 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/variables/selector.py +20 -9
- flaremc-0.2.4/flaremc.egg-info/PKG-INFO +82 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flaremc.egg-info/SOURCES.txt +1 -2
- {flaremc-0.2.2 → flaremc-0.2.4}/pyproject.toml +1 -1
- flaremc-0.2.2/PKG-INFO +0 -512
- flaremc-0.2.2/README.md +0 -501
- flaremc-0.2.2/flare/control_flow.py +0 -193
- flaremc-0.2.2/flare/variables/bigscore.py +0 -558
- flaremc-0.2.2/flare/variables/float32.py +0 -434
- flaremc-0.2.2/flare/variables/float64.py +0 -323
- flaremc-0.2.2/flare/variables/score.py +0 -599
- flaremc-0.2.2/flaremc.egg-info/PKG-INFO +0 -512
- flaremc-0.2.2/tests/test_flare.py +0 -96
- {flaremc-0.2.2 → flaremc-0.2.4}/LICENSE +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/__main__.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/math.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/nbt_schema.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/types.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/validator/__init__.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/validator/core.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/validator/parser.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flare/variables/storage.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flaremc.egg-info/dependency_links.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flaremc.egg-info/entry_points.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flaremc.egg-info/requires.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flaremc.egg-info/top_level.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/flarevsc/node_modules/flatted/python/flatted.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.4}/setup.cfg +0 -0
flaremc-0.2.4/PKG-INFO
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flaremc
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: Flare datapack compiler framework
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: mcemu
|
|
9
|
+
Requires-Dist: watchdog
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
<div align="center">
|
|
13
|
+
<img src="docs/public/assets/icon_transparent.png" width="200" alt="Flare Logo">
|
|
14
|
+
<h1>Flare 🔥</h1>
|
|
15
|
+
<p><b>Programmatic Minecraft Datapacks in Python</b></p>
|
|
16
|
+
<p>Write Minecraft logic using full Python power: scores, NBT, execute chains, recursion, and more. Compile to optimized datapacks instantly.</p>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<br>
|
|
20
|
+
|
|
21
|
+
**Read the full documentation at: [flare.oguzhanumutlu.com](https://flare.oguzhanumutlu.com)**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## What is Flare?
|
|
26
|
+
|
|
27
|
+
Flare is a modern framework for building Minecraft datapacks natively in Python. It bridges the gap between Python's high-level elegance and Minecraft's native `mcfunction` performance. You can use standard Python syntax, variables, and math, and Flare automatically translates and compiles your logic into highly-optimized, scoreboard-driven datapacks.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install flaremc
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start: Advanced Math & NBT
|
|
36
|
+
|
|
37
|
+
With Flare, writing advanced datapack logic is incredibly clean. Below is a quick example of defining variables, doing advanced floating-point math natively in Minecraft, running terminal commands, and interacting with NBT.
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from flare import namespace, score, math, nbt, expand
|
|
41
|
+
|
|
42
|
+
# Define your datapack namespace
|
|
43
|
+
namespace("my_pack")
|
|
44
|
+
|
|
45
|
+
# Declare a scoreboard variable and initialize it to 10
|
|
46
|
+
x = score(10)
|
|
47
|
+
|
|
48
|
+
# Compute math dynamically using native scoreboard approximations (Taylor series, CORDIC, etc.)
|
|
49
|
+
# All complex math compiles to highly optimized raw scoreboard operations!
|
|
50
|
+
result = math.sin(x) * math.sqrt(x)
|
|
51
|
+
|
|
52
|
+
# Print the dynamic float result back to the game seamlessly
|
|
53
|
+
print(f"The result is: {result}")
|
|
54
|
+
|
|
55
|
+
# Interact seamlessly with Minecraft's NBT environment
|
|
56
|
+
player_data = @a.Data[dict]
|
|
57
|
+
|
|
58
|
+
# Flare smartly manages conditional blocks and inlines commands when appropriate
|
|
59
|
+
if expand(x > 5):
|
|
60
|
+
say "X is greater than 5!"
|
|
61
|
+
kill @e[type=zombie, distance=..10]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Compile & Run
|
|
65
|
+
|
|
66
|
+
To compile your datapack to a `.mcfunction` structure, simply run:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
flare main.py
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
To compile and immediately run it using the built-in emulator:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
flare main.py --run
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Documentation
|
|
79
|
+
|
|
80
|
+
Ready to unleash the full power of Python in Minecraft?
|
|
81
|
+
|
|
82
|
+
Check out the interactive playground and full documentation at **[flare.oguzhanumutlu.com](https://flare.oguzhanumutlu.com)**!
|
flaremc-0.2.4/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="docs/public/assets/icon_transparent.png" width="200" alt="Flare Logo">
|
|
3
|
+
<h1>Flare 🔥</h1>
|
|
4
|
+
<p><b>Programmatic Minecraft Datapacks in Python</b></p>
|
|
5
|
+
<p>Write Minecraft logic using full Python power: scores, NBT, execute chains, recursion, and more. Compile to optimized datapacks instantly.</p>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<br>
|
|
9
|
+
|
|
10
|
+
**Read the full documentation at: [flare.oguzhanumutlu.com](https://flare.oguzhanumutlu.com)**
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What is Flare?
|
|
15
|
+
|
|
16
|
+
Flare is a modern framework for building Minecraft datapacks natively in Python. It bridges the gap between Python's high-level elegance and Minecraft's native `mcfunction` performance. You can use standard Python syntax, variables, and math, and Flare automatically translates and compiles your logic into highly-optimized, scoreboard-driven datapacks.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install flaremc
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start: Advanced Math & NBT
|
|
25
|
+
|
|
26
|
+
With Flare, writing advanced datapack logic is incredibly clean. Below is a quick example of defining variables, doing advanced floating-point math natively in Minecraft, running terminal commands, and interacting with NBT.
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from flare import namespace, score, math, nbt, expand
|
|
30
|
+
|
|
31
|
+
# Define your datapack namespace
|
|
32
|
+
namespace("my_pack")
|
|
33
|
+
|
|
34
|
+
# Declare a scoreboard variable and initialize it to 10
|
|
35
|
+
x = score(10)
|
|
36
|
+
|
|
37
|
+
# Compute math dynamically using native scoreboard approximations (Taylor series, CORDIC, etc.)
|
|
38
|
+
# All complex math compiles to highly optimized raw scoreboard operations!
|
|
39
|
+
result = math.sin(x) * math.sqrt(x)
|
|
40
|
+
|
|
41
|
+
# Print the dynamic float result back to the game seamlessly
|
|
42
|
+
print(f"The result is: {result}")
|
|
43
|
+
|
|
44
|
+
# Interact seamlessly with Minecraft's NBT environment
|
|
45
|
+
player_data = @a.Data[dict]
|
|
46
|
+
|
|
47
|
+
# Flare smartly manages conditional blocks and inlines commands when appropriate
|
|
48
|
+
if expand(x > 5):
|
|
49
|
+
say "X is greater than 5!"
|
|
50
|
+
kill @e[type=zombie, distance=..10]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Compile & Run
|
|
54
|
+
|
|
55
|
+
To compile your datapack to a `.mcfunction` structure, simply run:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
flare main.py
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
To compile and immediately run it using the built-in emulator:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
flare main.py --run
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Documentation
|
|
68
|
+
|
|
69
|
+
Ready to unleash the full power of Python in Minecraft?
|
|
70
|
+
|
|
71
|
+
Check out the interactive playground and full documentation at **[flare.oguzhanumutlu.com](https://flare.oguzhanumutlu.com)**!
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
from .compiler import _flatten_and, _eval_to_bool_score, _compile_relational
|
|
2
2
|
from .context import namespace, export, tick, push_context, runcommand, files, temp_obj, constant_obj, vars_obj, \
|
|
3
|
-
constants, _flare_assign, _flare_aug_assign, _flare_print, dbg, _flare_return
|
|
4
|
-
from .control_flow import _flare_if, _flare_while, _flare_for, _flare_with, _flare_break, _flare_continue
|
|
3
|
+
constants, _flare_assign, _flare_aug_assign, _flare_print, dbg, _flare_return, _flare_in, _flare_notin
|
|
4
|
+
from .control_flow import _flare_if, _flare_while, _flare_for, _flare_with, _flare_break, _flare_continue, expand
|
|
5
5
|
from .execute_modifiers import _as, at, positioned, aligned, facing, anchored, rotated, dimension, applyon, on, summon, \
|
|
6
6
|
store, ExecuteChain, StoreExecuteChain
|
|
7
7
|
from .math import round_, floor, ceil
|
|
8
8
|
from .types import NBTType, byte, boolean, short, long, double, array
|
|
9
9
|
from .variables import score, nbt, fixed, tagged, ref, getscore, storage, nbtbyte, nbtbool, nbtshort, nbtint, nbtlong, \
|
|
10
|
-
nbtfloat, nbtdouble, nbtstr, nbtlist, nbtdict, nbtbytearray, nbtintarray, nbtlongarray, selector
|
|
10
|
+
nbtfloat, nbtdouble, nbtstr, nbtlist, nbtdict, nbtbytearray, nbtintarray, nbtlongarray, selector, bigscore, \
|
|
11
|
+
bigfixed, float64, float32, complex
|
|
11
12
|
|
|
12
13
|
__all__ = ["round_", "floor", "ceil", "namespace", "export", "tick", "score", "nbt", "fixed", "tagged", "ref",
|
|
13
14
|
"getscore", "storage", "_flare_print", "dbg", "nbtbyte", "nbtbool", "nbtshort", "nbtint", "nbtlong",
|
|
14
15
|
"nbtfloat", "nbtdouble", "nbtstr", "nbtlist", "nbtdict", "nbtbytearray", "nbtintarray", "nbtlongarray",
|
|
15
16
|
"selector", "_as", "at", "positioned", "aligned", "facing", "anchored", "rotated", "dimension", "applyon",
|
|
16
|
-
"on", "summon", "store", "ExecuteChain", "StoreExecuteChain", "array"
|
|
17
|
+
"on", "summon", "store", "ExecuteChain", "StoreExecuteChain", "array", "bigscore", "bigfixed", "float32",
|
|
18
|
+
"float64", "complex", "byte", "boolean", "short", "long", "double", "expand"]
|
|
@@ -95,7 +95,8 @@ def _build_datapack_inner(file_path: str, cli_overrides: dict = None):
|
|
|
95
95
|
|
|
96
96
|
global_env = {"__name__": "__main__", "__file__": abs_path}
|
|
97
97
|
exec(
|
|
98
|
-
"from flare import _flare_assign, _flare_aug_assign, _flare_if, _flare_while, _flare_for, _flare_with, runcommand, _flare_return, _flare_break, _flare_continue\n"
|
|
98
|
+
"from flare import _flare_assign, _flare_aug_assign, _flare_if, _flare_while, _flare_for, _flare_with, runcommand, _flare_return, _flare_break, _flare_continue, _flare_in, _flare_notin\n"
|
|
99
|
+
"from flare import context as ctx\n"
|
|
99
100
|
"from flare.command_parser import interpolate_command\n"
|
|
100
101
|
"from flare import _flare_print as print, selector, _as, at, positioned, aligned, facing, anchored, rotated, dimension, applyon, on, summon, store\n"
|
|
101
102
|
"from flare import nbt, score, fixed, tagged, ref, getscore, storage, array, byte, boolean, short, long, double\n"
|
|
@@ -153,8 +154,14 @@ def _build_datapack_inner(file_path: str, cli_overrides: dict = None):
|
|
|
153
154
|
if ":" in filename:
|
|
154
155
|
ns, name = filename.split(":", 1)
|
|
155
156
|
file_p = build_dir / "data" / ns / "functions" / f"{name}.mcfunction"
|
|
157
|
+
is_top_level = "generated_" not in name and "while_" not in name and name not in ("main", "load")
|
|
156
158
|
else:
|
|
157
159
|
file_p = build_dir / "data" / context._current_namespace / "functions" / f"{filename}.mcfunction"
|
|
160
|
+
is_top_level = "generated_" not in filename and "while_" not in filename and filename not in ("main",
|
|
161
|
+
"load")
|
|
162
|
+
|
|
163
|
+
if is_top_level and lines and lines[-1] in ("return 1", "return 0"):
|
|
164
|
+
lines.pop()
|
|
158
165
|
|
|
159
166
|
file_p.parent.mkdir(parents=True, exist_ok=True)
|
|
160
167
|
with open(file_p, "w") as f:
|
|
@@ -71,7 +71,7 @@ def interpolate_command(command: str, local_vars: dict, global_vars: dict) -> st
|
|
|
71
71
|
elif not is_key and ident in local_vars:
|
|
72
72
|
val = local_vars[ident]
|
|
73
73
|
if hasattr(val, "addr"):
|
|
74
|
-
output.append(val.
|
|
74
|
+
output.append(val._addr)
|
|
75
75
|
elif hasattr(val, "target"):
|
|
76
76
|
output.append(val.target)
|
|
77
77
|
elif isinstance(val, dict) and output and output[-1].endswith("**"):
|
|
@@ -88,7 +88,7 @@ def interpolate_command(command: str, local_vars: dict, global_vars: dict) -> st
|
|
|
88
88
|
elif not is_key and ident in global_vars:
|
|
89
89
|
val = global_vars[ident]
|
|
90
90
|
if hasattr(val, "addr"):
|
|
91
|
-
output.append(val.
|
|
91
|
+
output.append(val._addr)
|
|
92
92
|
elif hasattr(val, "target"):
|
|
93
93
|
output.append(val.target)
|
|
94
94
|
elif isinstance(val, dict) and output and output[-1].endswith("**"):
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from . import context as ctx
|
|
2
2
|
from .context import runcommand, temp_obj
|
|
3
3
|
from .variables import score, BinaryOp, UnaryOp, getscore
|
|
4
|
+
from .variables.core import addr
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
def _compile_relational(node, invert=False):
|
|
@@ -19,8 +20,7 @@ def _compile_relational(node, invert=False):
|
|
|
19
20
|
if isinstance(left, (int, float)):
|
|
20
21
|
left = getscore(left)
|
|
21
22
|
else:
|
|
22
|
-
t = score(addr=f"!c{ctx.
|
|
23
|
-
ctx._temp_id += 1
|
|
23
|
+
t = score(addr=f"!c{ctx.next_temp_id()} {temp_obj}")
|
|
24
24
|
if isinstance(left, (BinaryOp, UnaryOp)):
|
|
25
25
|
left._eval_into(t)
|
|
26
26
|
else:
|
|
@@ -29,52 +29,52 @@ def _compile_relational(node, invert=False):
|
|
|
29
29
|
|
|
30
30
|
if not isinstance(right, score):
|
|
31
31
|
if isinstance(right, (int, float)):
|
|
32
|
-
right = getscore(right, left.
|
|
32
|
+
right = getscore(right, left._multiplier)
|
|
33
33
|
else:
|
|
34
|
-
t = score(addr=f"!c{ctx.
|
|
35
|
-
ctx._temp_id += 1
|
|
34
|
+
t = score(addr=f"!c{ctx.next_temp_id()} {temp_obj}", multiplier=left._multiplier)
|
|
36
35
|
if isinstance(right, (BinaryOp, UnaryOp)):
|
|
37
36
|
right._eval_into(t)
|
|
38
37
|
else:
|
|
39
38
|
t.__iset__(right)
|
|
40
39
|
right = t
|
|
41
40
|
|
|
42
|
-
if left.
|
|
43
|
-
t = score(addr=f"!c{ctx.
|
|
44
|
-
ctx._temp_id += 1
|
|
41
|
+
if left._multiplier != right._multiplier:
|
|
42
|
+
t = score(addr=f"!c{ctx.next_temp_id()} {temp_obj}", multiplier=left._multiplier)
|
|
45
43
|
t.__iset__(right)
|
|
46
44
|
right = t
|
|
47
45
|
|
|
48
|
-
return f"{keyword} score {left
|
|
46
|
+
return f"{keyword} score {addr(left)} {mcop} {addr(right)}"
|
|
49
47
|
|
|
50
48
|
|
|
51
49
|
def _eval_to_bool_score(node):
|
|
52
|
-
dest = score(addr=f"!b{ctx.
|
|
53
|
-
|
|
54
|
-
runcommand(f"scoreboard players set {dest.addr} 0")
|
|
50
|
+
dest = score(addr=f"!b{ctx.next_temp_id()} {temp_obj}")
|
|
51
|
+
runcommand(f"scoreboard players set {addr(dest)} 0")
|
|
55
52
|
|
|
56
53
|
if isinstance(node, BinaryOp) and node.op == "or":
|
|
57
54
|
left_conds = _flatten_and(node.left)
|
|
58
|
-
runcommand(f"execute {' '.join(left_conds)} run scoreboard players set {dest
|
|
55
|
+
runcommand(f"execute {' '.join(left_conds)} run scoreboard players set {addr(dest)} 1")
|
|
59
56
|
right_conds = _flatten_and(node.right)
|
|
60
57
|
runcommand(
|
|
61
|
-
f"execute if score {dest
|
|
58
|
+
f"execute if score {addr(dest)} matches 0 {' '.join(right_conds)} run scoreboard players set {addr(dest)} 1")
|
|
62
59
|
return dest
|
|
63
60
|
|
|
64
61
|
if isinstance(node, UnaryOp) and node.op == "not":
|
|
65
62
|
sub_dest = _eval_to_bool_score(node.operand)
|
|
66
|
-
runcommand(f"execute if score {sub_dest
|
|
63
|
+
runcommand(f"execute if score {addr(sub_dest)} matches 0 run scoreboard players set {addr(dest)} 1")
|
|
67
64
|
return dest
|
|
68
65
|
|
|
69
66
|
if isinstance(node, (BinaryOp, UnaryOp)):
|
|
70
|
-
t = score(addr=f"!b{ctx.
|
|
71
|
-
ctx._temp_id += 1
|
|
67
|
+
t = score(addr=f"!b{ctx.next_temp_id()} {temp_obj}")
|
|
72
68
|
node._eval_into(t)
|
|
73
|
-
runcommand(f"execute unless score {t
|
|
69
|
+
runcommand(f"execute unless score {addr(t)} matches 0 run scoreboard players set {addr(dest)} 1")
|
|
70
|
+
return dest
|
|
71
|
+
|
|
72
|
+
if hasattr(type(node), "_eval_into") or hasattr(node, "_addr"):
|
|
73
|
+
runcommand(f"execute unless score {addr(node)} matches 0 run scoreboard players set {addr(dest)} 1")
|
|
74
74
|
return dest
|
|
75
75
|
|
|
76
76
|
if node:
|
|
77
|
-
runcommand(f"scoreboard players set {dest
|
|
77
|
+
runcommand(f"scoreboard players set {addr(dest)} 1")
|
|
78
78
|
return dest
|
|
79
79
|
|
|
80
80
|
|
|
@@ -84,4 +84,4 @@ def _flatten_and(node, invert=False):
|
|
|
84
84
|
|
|
85
85
|
dest = _eval_to_bool_score(node)
|
|
86
86
|
keyword = "unless" if invert else "if"
|
|
87
|
-
return [f"{keyword} score {dest
|
|
87
|
+
return [f"{keyword} score {addr(dest)} matches 1"]
|
|
@@ -8,9 +8,39 @@ current_file = "main"
|
|
|
8
8
|
_current_namespace = "flare"
|
|
9
9
|
functions = {}
|
|
10
10
|
constants = {}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DynamicVar:
|
|
14
|
+
def __init__(self, fmt):
|
|
15
|
+
self.fmt = fmt
|
|
16
|
+
|
|
17
|
+
def __str__(self):
|
|
18
|
+
return self.fmt.format(ns=_current_namespace)
|
|
19
|
+
|
|
20
|
+
def __format__(self, format_spec):
|
|
21
|
+
return format(str(self), format_spec)
|
|
22
|
+
|
|
23
|
+
def __add__(self, other):
|
|
24
|
+
return str(self) + other
|
|
25
|
+
|
|
26
|
+
def __radd__(self, other):
|
|
27
|
+
return other + str(self)
|
|
28
|
+
|
|
29
|
+
def __hash__(self):
|
|
30
|
+
return hash(str(self))
|
|
31
|
+
|
|
32
|
+
def __eq__(self, other):
|
|
33
|
+
return str(self) == str(other)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
constant_obj = DynamicVar("__{ns}__constant__")
|
|
37
|
+
vars_obj = DynamicVar("__{ns}__vars__")
|
|
38
|
+
temp_obj = DynamicVar("__{ns}__temp__")
|
|
39
|
+
temp_storage = DynamicVar("{ns}:__flare_temp__")
|
|
40
|
+
vars_storage = DynamicVar("{ns}:__flare_vars__")
|
|
41
|
+
args_storage = DynamicVar("{ns}:__flare_args__")
|
|
42
|
+
returns_storage = DynamicVar("{ns}:__flare_returns__")
|
|
43
|
+
|
|
14
44
|
_temp_id = 0
|
|
15
45
|
_func_id = 0
|
|
16
46
|
_objective_offset = 0
|
|
@@ -26,6 +56,20 @@ minecraft_version = "1.20.4"
|
|
|
26
56
|
nbt_schema_missing = "error"
|
|
27
57
|
|
|
28
58
|
|
|
59
|
+
def next_temp_id():
|
|
60
|
+
global _temp_id
|
|
61
|
+
got = _temp_id
|
|
62
|
+
_temp_id += 1
|
|
63
|
+
return got
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def next_func_id():
|
|
67
|
+
global _func_id
|
|
68
|
+
got = _func_id
|
|
69
|
+
_func_id += 1
|
|
70
|
+
return got
|
|
71
|
+
|
|
72
|
+
|
|
29
73
|
def reset_context():
|
|
30
74
|
global files, current_file, _current_namespace, functions, constants, _temp_id, _func_id, _objective_offset, _constant_offset, validation_level, minecraft_version, nbt_schema_missing, _recursive_functions, _in_recursive_context, return_types, _logical_func
|
|
31
75
|
files = {"main": []}
|
|
@@ -91,9 +135,11 @@ def push_context(name: str):
|
|
|
91
135
|
return _ContextManager(name)
|
|
92
136
|
|
|
93
137
|
|
|
94
|
-
def namespace(name: str):
|
|
138
|
+
def namespace(name: str | None = None):
|
|
95
139
|
global _current_namespace
|
|
96
|
-
|
|
140
|
+
if name is not None:
|
|
141
|
+
_current_namespace = name
|
|
142
|
+
return _current_namespace
|
|
97
143
|
|
|
98
144
|
|
|
99
145
|
from .validator import validate_command, FlareCommandValidationError
|
|
@@ -138,28 +184,28 @@ def _flare_print(*args):
|
|
|
138
184
|
|
|
139
185
|
if isinstance(arg, score):
|
|
140
186
|
if getattr(arg, "multiplier", 1.0) != 1.0:
|
|
141
|
-
scale_str = f"{arg.
|
|
187
|
+
scale_str = f"{arg._multiplier:.15f}".rstrip("0")
|
|
142
188
|
if scale_str.endswith("."):
|
|
143
189
|
scale_str += "0"
|
|
144
190
|
runcommand(
|
|
145
|
-
f"execute store result storage
|
|
146
|
-
components.append({"nbt": f"__flare_debug_{i}", "storage":
|
|
191
|
+
f"execute store result storage {temp_storage} __flare_debug_{i} double {scale_str} run scoreboard players get {addr(arg)}")
|
|
192
|
+
components.append({"nbt": f"__flare_debug_{i}", "storage": str(temp_storage)})
|
|
147
193
|
else:
|
|
148
|
-
name, obj = arg.
|
|
194
|
+
name, obj = arg._addr.split(" ", 1)
|
|
149
195
|
components.append({"score": {"name": name, "objective": obj}})
|
|
150
196
|
elif isinstance(arg, nbt):
|
|
151
|
-
nbt_comp = {"nbt": arg.
|
|
152
|
-
if arg.
|
|
197
|
+
nbt_comp = {"nbt": arg._path or "{}"}
|
|
198
|
+
if arg._path == "":
|
|
153
199
|
nbt_comp["nbt"] = "{}"
|
|
154
200
|
|
|
155
|
-
if arg.
|
|
156
|
-
nbt_comp["storage"] = arg.
|
|
157
|
-
elif arg.
|
|
158
|
-
nbt_comp["entity"] = arg.
|
|
159
|
-
elif arg.
|
|
160
|
-
nbt_comp["block"] = arg.
|
|
201
|
+
if arg._target_type == "storage":
|
|
202
|
+
nbt_comp["storage"] = arg._target
|
|
203
|
+
elif arg._target_type == "entity":
|
|
204
|
+
nbt_comp["entity"] = arg._target
|
|
205
|
+
elif arg._target_type == "block":
|
|
206
|
+
nbt_comp["block"] = arg._target
|
|
161
207
|
|
|
162
|
-
if arg.
|
|
208
|
+
if arg._path == "":
|
|
163
209
|
nbt_comp["nbt"] = "{}"
|
|
164
210
|
|
|
165
211
|
components.append(nbt_comp)
|
|
@@ -178,15 +224,21 @@ def _flare_print(*args):
|
|
|
178
224
|
runcommand(f"tellraw @a {cmd_text}")
|
|
179
225
|
|
|
180
226
|
|
|
181
|
-
def export(func=None, *, append=False):
|
|
227
|
+
def export(func=None, *, name=None, append=False):
|
|
182
228
|
from flare import score # avoid circular import
|
|
229
|
+
|
|
230
|
+
if isinstance(func, str):
|
|
231
|
+
name = func
|
|
232
|
+
func = None
|
|
233
|
+
|
|
183
234
|
if func is None:
|
|
184
235
|
def wrapper(f):
|
|
185
|
-
return export(f, append=append)
|
|
236
|
+
return export(f, name=name, append=append)
|
|
186
237
|
|
|
187
238
|
return wrapper
|
|
188
239
|
|
|
189
|
-
|
|
240
|
+
actual_name = name if name is not None else func.__name__
|
|
241
|
+
func_name = f"{_current_namespace}:{actual_name}"
|
|
190
242
|
if func_name in files and not append:
|
|
191
243
|
raise ValueError(f"Function {func_name} already exists. Use @export(append=True) to append.")
|
|
192
244
|
|
|
@@ -208,9 +260,9 @@ def export(func=None, *, append=False):
|
|
|
208
260
|
kwargs[name] = score(addr=f"{func.__name__}_{name} {vars_obj}")
|
|
209
261
|
elif hasattr(anno, "__name__") and anno.__name__ in ("nbt", "_TypedNBT"):
|
|
210
262
|
if is_recursive:
|
|
211
|
-
kwargs[name] = anno(addr=f"storage
|
|
263
|
+
kwargs[name] = anno(addr=f"storage {args_storage} {func.__name__}_{name}[-1]")
|
|
212
264
|
else:
|
|
213
|
-
kwargs[name] = anno(addr=f"storage
|
|
265
|
+
kwargs[name] = anno(addr=f"storage {args_storage} {func.__name__}_{name}")
|
|
214
266
|
elif anno is not inspect.Signature.empty:
|
|
215
267
|
raise TypeError(f"Argument '{name}' must be typed as score or nbt, not {anno}")
|
|
216
268
|
else:
|
|
@@ -235,24 +287,25 @@ def export(func=None, *, append=False):
|
|
|
235
287
|
global _temp_id
|
|
236
288
|
bound = sig.bind(*args, **call_kwargs)
|
|
237
289
|
bound.apply_defaults()
|
|
290
|
+
from .variables.core import addr
|
|
238
291
|
for arg_name, arg_val in bound.arguments.items():
|
|
239
292
|
target = kwargs[arg_name]
|
|
240
293
|
|
|
241
294
|
if is_recursive and isinstance(target, nbt):
|
|
242
|
-
base_addr = f"storage
|
|
295
|
+
base_addr = f"storage {args_storage} {func.__name__}_{arg_name}"
|
|
243
296
|
if isinstance(arg_val, (int, float, str)):
|
|
244
297
|
runcommand(f"data modify {base_addr} append value {json.dumps(arg_val)}")
|
|
245
298
|
elif isinstance(arg_val, nbt):
|
|
246
|
-
runcommand(f"data modify {base_addr} append from {arg_val
|
|
299
|
+
runcommand(f"data modify {base_addr} append from {addr(arg_val)}")
|
|
247
300
|
elif isinstance(arg_val, score):
|
|
248
301
|
runcommand(f"data modify {base_addr} append value 0")
|
|
249
302
|
runcommand(
|
|
250
|
-
f"execute store result {base_addr}[-1] int {1 / arg_val.
|
|
303
|
+
f"execute store result {base_addr}[-1] int {1 / arg_val._multiplier} run scoreboard players get {addr(arg_val)}")
|
|
251
304
|
elif hasattr(type(arg_val), "_eval_into"):
|
|
252
|
-
temp = nbt(addr=f"storage
|
|
305
|
+
temp = nbt(addr=f"storage {temp_storage} !t{_temp_id}", datatype=target._type)
|
|
253
306
|
_temp_id += 1
|
|
254
307
|
arg_val._eval_into(temp)
|
|
255
|
-
runcommand(f"data modify {base_addr} append from {temp
|
|
308
|
+
runcommand(f"data modify {base_addr} append from {addr(temp)}")
|
|
256
309
|
else:
|
|
257
310
|
target.__iset__(arg_val)
|
|
258
311
|
|
|
@@ -261,7 +314,7 @@ def export(func=None, *, append=False):
|
|
|
261
314
|
if is_recursive:
|
|
262
315
|
for arg_name in bound.arguments.keys():
|
|
263
316
|
if isinstance(kwargs[arg_name], nbt):
|
|
264
|
-
base_addr = f"storage
|
|
317
|
+
base_addr = f"storage {args_storage} {func.__name__}_{arg_name}"
|
|
265
318
|
runcommand(f"data remove {base_addr}[-1]")
|
|
266
319
|
|
|
267
320
|
ret_anno = return_types.get(func_name, sig.return_annotation)
|
|
@@ -272,15 +325,15 @@ def export(func=None, *, append=False):
|
|
|
272
325
|
temp_ret = score(addr=f"!ret{_temp_id} {temp_obj}")
|
|
273
326
|
_temp_id += 1
|
|
274
327
|
runcommand(
|
|
275
|
-
f"scoreboard players operation {temp_ret
|
|
328
|
+
f"scoreboard players operation {addr(temp_ret)} = {func_name.replace(":", "_")}_ret {vars_obj}")
|
|
276
329
|
if ret_anno.__name__ in ("fixed", "_PrecisionScore"):
|
|
277
330
|
pass
|
|
278
331
|
return temp_ret
|
|
279
332
|
else:
|
|
280
|
-
temp_ret = nbt(addr=f"storage
|
|
333
|
+
temp_ret = nbt(addr=f"storage {temp_storage} !ret{_temp_id}")
|
|
281
334
|
_temp_id += 1
|
|
282
335
|
runcommand(
|
|
283
|
-
f"data modify {temp_ret
|
|
336
|
+
f"data modify {addr(temp_ret)} set from storage {returns_storage} {func_name.replace(':', '_')}")
|
|
284
337
|
return temp_ret
|
|
285
338
|
|
|
286
339
|
proxy = ProxyFunction()
|
|
@@ -310,6 +363,18 @@ def export(func=None, *, append=False):
|
|
|
310
363
|
return proxy
|
|
311
364
|
|
|
312
365
|
|
|
366
|
+
def _flare_in(item, container):
|
|
367
|
+
if hasattr(container, "__in__"):
|
|
368
|
+
return container.__in__(item)
|
|
369
|
+
return item in container
|
|
370
|
+
|
|
371
|
+
def _flare_notin(item, container):
|
|
372
|
+
if hasattr(container, "__notin__"):
|
|
373
|
+
return container.__notin__(item)
|
|
374
|
+
if hasattr(container, "__in__"):
|
|
375
|
+
return ~container.__in__(item)
|
|
376
|
+
return item not in container
|
|
377
|
+
|
|
313
378
|
def _flare_assign(var_name, value, local_env, global_env):
|
|
314
379
|
if var_name in local_env:
|
|
315
380
|
target = local_env[var_name]
|
|
@@ -402,12 +467,12 @@ def _flare_return(value):
|
|
|
402
467
|
target.__iset__(value)
|
|
403
468
|
else:
|
|
404
469
|
if inspect.isclass(ret_anno) and issubclass(ret_anno, nbt):
|
|
405
|
-
target = ret_anno(addr=f"storage
|
|
470
|
+
target = ret_anno(addr=f"storage {returns_storage} {func_name.replace(':', '_')}")
|
|
406
471
|
else:
|
|
407
472
|
datatype = None
|
|
408
473
|
if hasattr(ret_anno, "__origin__") or isinstance(ret_anno, type):
|
|
409
474
|
datatype = getattr(ret_anno, "__origin__", ret_anno)
|
|
410
|
-
target = nbt(addr=f"storage
|
|
475
|
+
target = nbt(addr=f"storage {returns_storage} {func_name.replace(':', '_')}", datatype=datatype)
|
|
411
476
|
target.__iset__(value)
|
|
412
477
|
|
|
413
478
|
runcommand("return 1")
|