dfpyre 0.6.2__py3-none-any.whl → 0.7.0__py3-none-any.whl
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.
Potentially problematic release.
This version of dfpyre might be problematic. Click here for more details.
- dfpyre/actiondump.py +72 -0
- dfpyre/data/actiondump_min.json +1 -0
- dfpyre/items.py +59 -8
- dfpyre/pyre.py +133 -158
- dfpyre/scriptgen.py +10 -2
- dfpyre/util.py +28 -0
- {dfpyre-0.6.2.dist-info → dfpyre-0.7.0.dist-info}/METADATA +16 -3
- dfpyre-0.7.0.dist-info/RECORD +12 -0
- dfpyre/data/data.json +0 -1
- dfpyre-0.6.2.dist-info/RECORD +0 -10
- {dfpyre-0.6.2.dist-info → dfpyre-0.7.0.dist-info}/LICENSE +0 -0
- {dfpyre-0.6.2.dist-info → dfpyre-0.7.0.dist-info}/WHEEL +0 -0
dfpyre/items.py
CHANGED
|
@@ -4,19 +4,28 @@ Contains class definitions for code items.
|
|
|
4
4
|
|
|
5
5
|
from enum import Enum
|
|
6
6
|
import re
|
|
7
|
-
from typing import Literal,
|
|
7
|
+
from typing import Literal, Any
|
|
8
8
|
from dfpyre.style import is_ampersand_coded, ampersand_to_minimessage
|
|
9
|
+
from dfpyre.util import PyreException, warn
|
|
9
10
|
from mcitemlib.itemlib import Item as NbtItem
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
NUMBER_REGEX = r'-?\d*\.?\d+'
|
|
14
|
+
VAR_SHORTHAND_CHAR = '$'
|
|
15
|
+
VAR_SCOPES = {'g': 'unsaved', 's': 'saved', 'l': 'local', 'i': 'line'}
|
|
13
16
|
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
def convert_argument(arg: Any):
|
|
19
|
+
if type(arg) in {int, float}:
|
|
20
|
+
return num(arg)
|
|
21
|
+
elif isinstance(arg, str):
|
|
22
|
+
if len(arg) > 2 and arg[0] == VAR_SHORTHAND_CHAR and arg[1] in VAR_SCOPES:
|
|
23
|
+
return var(arg[2:], VAR_SCOPES[arg[1]])
|
|
24
|
+
return text(arg)
|
|
25
|
+
return arg
|
|
17
26
|
|
|
18
27
|
|
|
19
|
-
def _add_slot(d:
|
|
28
|
+
def _add_slot(d: dict, slot: int|None):
|
|
20
29
|
if slot is not None:
|
|
21
30
|
d['slot'] = slot
|
|
22
31
|
|
|
@@ -32,6 +41,9 @@ class item(NbtItem):
|
|
|
32
41
|
_add_slot(formatted_dict, slot)
|
|
33
42
|
return formatted_dict
|
|
34
43
|
|
|
44
|
+
def __repr__(self) -> str:
|
|
45
|
+
return f'{self.__class__.__name__}({self.get_id()}, {self.get_count()})'
|
|
46
|
+
|
|
35
47
|
|
|
36
48
|
class string:
|
|
37
49
|
"""
|
|
@@ -46,6 +58,9 @@ class string:
|
|
|
46
58
|
formatted_dict = {"item": {"id": self.type, "data": {"name": self.value}}}
|
|
47
59
|
_add_slot(formatted_dict, slot)
|
|
48
60
|
return formatted_dict
|
|
61
|
+
|
|
62
|
+
def __repr__(self) -> str:
|
|
63
|
+
return f'{self.__class__.__name__}("{self.value}")'
|
|
49
64
|
|
|
50
65
|
|
|
51
66
|
class text:
|
|
@@ -64,6 +79,9 @@ class text:
|
|
|
64
79
|
_add_slot(formatted_dict, slot)
|
|
65
80
|
return formatted_dict
|
|
66
81
|
|
|
82
|
+
def __repr__(self) -> str:
|
|
83
|
+
return f'{self.__class__.__name__}("{self.value}")'
|
|
84
|
+
|
|
67
85
|
|
|
68
86
|
class num:
|
|
69
87
|
"""
|
|
@@ -79,6 +97,9 @@ class num:
|
|
|
79
97
|
_add_slot(formatted_dict, slot)
|
|
80
98
|
return formatted_dict
|
|
81
99
|
|
|
100
|
+
def __repr__(self) -> str:
|
|
101
|
+
return f'{self.__class__.__name__}({self.value})'
|
|
102
|
+
|
|
82
103
|
|
|
83
104
|
class loc:
|
|
84
105
|
"""
|
|
@@ -110,6 +131,9 @@ class loc:
|
|
|
110
131
|
_add_slot(formatted_dict, slot)
|
|
111
132
|
return formatted_dict
|
|
112
133
|
|
|
134
|
+
def __repr__(self) -> str:
|
|
135
|
+
return f'{self.__class__.__name__}({self.x}, {self.y}, {self.z}, {self.pitch}, {self.yaw})'
|
|
136
|
+
|
|
113
137
|
|
|
114
138
|
class var:
|
|
115
139
|
"""
|
|
@@ -126,6 +150,9 @@ class var:
|
|
|
126
150
|
_add_slot(formatted_dict, slot)
|
|
127
151
|
return formatted_dict
|
|
128
152
|
|
|
153
|
+
def __repr__(self) -> str:
|
|
154
|
+
return f'{self.__class__.__name__}({self.scope}, "{self.name}")'
|
|
155
|
+
|
|
129
156
|
|
|
130
157
|
class sound:
|
|
131
158
|
"""
|
|
@@ -143,6 +170,9 @@ class sound:
|
|
|
143
170
|
_add_slot(formatted_dict, slot)
|
|
144
171
|
return formatted_dict
|
|
145
172
|
|
|
173
|
+
def __repr__(self) -> str:
|
|
174
|
+
return f'{self.__class__.__name__}(pitch: {self.pitch}, volume: {self.vol})'
|
|
175
|
+
|
|
146
176
|
|
|
147
177
|
class particle:
|
|
148
178
|
"""
|
|
@@ -157,6 +187,9 @@ class particle:
|
|
|
157
187
|
_add_slot(formatted_dict, slot)
|
|
158
188
|
return formatted_dict
|
|
159
189
|
|
|
190
|
+
def __repr__(self) -> str:
|
|
191
|
+
return f'{self.__class__.__name__}({self.particle_data})'
|
|
192
|
+
|
|
160
193
|
|
|
161
194
|
class potion:
|
|
162
195
|
"""
|
|
@@ -174,6 +207,9 @@ class potion:
|
|
|
174
207
|
_add_slot(formatted_dict, slot)
|
|
175
208
|
return formatted_dict
|
|
176
209
|
|
|
210
|
+
def __repr__(self) -> str:
|
|
211
|
+
return f'{self.__class__.__name__}(effect: {self.name}, duration: {self.dur}, amplifier: {self.amp})'
|
|
212
|
+
|
|
177
213
|
|
|
178
214
|
class gamevalue:
|
|
179
215
|
"""
|
|
@@ -190,6 +226,9 @@ class gamevalue:
|
|
|
190
226
|
_add_slot(formatted_dict, slot)
|
|
191
227
|
return formatted_dict
|
|
192
228
|
|
|
229
|
+
def __repr__(self) -> str:
|
|
230
|
+
return f'{self.__class__.__name__}({self.name}, target: {self.target})'
|
|
231
|
+
|
|
193
232
|
|
|
194
233
|
class vector:
|
|
195
234
|
"""
|
|
@@ -207,6 +246,9 @@ class vector:
|
|
|
207
246
|
_add_slot(formatted_dict, slot)
|
|
208
247
|
return formatted_dict
|
|
209
248
|
|
|
249
|
+
def __repr__(self) -> str:
|
|
250
|
+
return f'{self.__class__.__name__}({self.x}, {self.y}, {self.z})'
|
|
251
|
+
|
|
210
252
|
|
|
211
253
|
PARAMETER_TYPE_LOOKUP = ['txt', 'comp', 'num', 'loc', 'vec', 'snd', 'part', 'pot', 'item', 'any', 'var', 'list', 'dict']
|
|
212
254
|
|
|
@@ -241,7 +283,7 @@ class parameter:
|
|
|
241
283
|
self.optional = optional
|
|
242
284
|
self.description = description
|
|
243
285
|
self.note = note
|
|
244
|
-
self.default_value = default_value
|
|
286
|
+
self.default_value = convert_argument(default_value)
|
|
245
287
|
|
|
246
288
|
|
|
247
289
|
def format(self, slot: int):
|
|
@@ -259,10 +301,19 @@ class parameter:
|
|
|
259
301
|
formatted_dict['item']['data']['description'] = self.description
|
|
260
302
|
if self.note:
|
|
261
303
|
formatted_dict['item']['data']['note'] = self.note
|
|
262
|
-
if self.default_value is not None
|
|
263
|
-
|
|
304
|
+
if self.default_value is not None:
|
|
305
|
+
if not self.optional:
|
|
306
|
+
warn(f'For parameter "{self.name}": Default value cannot be set if optional is False.')
|
|
307
|
+
elif self.plural:
|
|
308
|
+
warn(f'For parameter "{self.name}": Default value cannot be set while plural is True.')
|
|
309
|
+
else:
|
|
310
|
+
formatted_dict['item']['data']['default_value'] = self.default_value.format(None)['item']
|
|
264
311
|
|
|
265
312
|
return formatted_dict
|
|
313
|
+
|
|
314
|
+
def __repr__(self) -> str:
|
|
315
|
+
raw_type = str(self.param_type).partition('.')[2]
|
|
316
|
+
return f'{self.__class__.__name__}({self.name}, type: {raw_type})'
|
|
266
317
|
|
|
267
318
|
|
|
268
319
|
def _some_or(value: Any, none_value: Any):
|
|
@@ -274,7 +325,7 @@ def _some_or(value: Any, none_value: Any):
|
|
|
274
325
|
return value
|
|
275
326
|
|
|
276
327
|
|
|
277
|
-
def item_from_dict(item_dict:
|
|
328
|
+
def item_from_dict(item_dict: dict) -> object:
|
|
278
329
|
item_id = item_dict['id']
|
|
279
330
|
item_data = item_dict['data']
|
|
280
331
|
|
dfpyre/pyre.py
CHANGED
|
@@ -4,25 +4,18 @@ A package for externally creating code templates for the DiamondFire Minecraft s
|
|
|
4
4
|
By Amp
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import base64
|
|
8
|
-
import gzip
|
|
9
7
|
import json
|
|
10
|
-
import os
|
|
11
8
|
from difflib import get_close_matches
|
|
12
9
|
import datetime
|
|
13
|
-
from typing import Tuple
|
|
10
|
+
from typing import Tuple
|
|
14
11
|
from enum import Enum
|
|
15
12
|
import socket
|
|
16
13
|
from mcitemlib.itemlib import Item as NbtItem
|
|
14
|
+
from dfpyre.util import *
|
|
17
15
|
from dfpyre.items import *
|
|
18
16
|
from dfpyre.scriptgen import generate_script, GeneratorFlags
|
|
17
|
+
from dfpyre.actiondump import CODEBLOCK_DATA, get_default_tags
|
|
19
18
|
|
|
20
|
-
COL_WARN = '\x1b[33m'
|
|
21
|
-
COL_RESET = '\x1b[0m'
|
|
22
|
-
COL_SUCCESS = '\x1b[32m'
|
|
23
|
-
COL_ERROR = '\x1b[31m'
|
|
24
|
-
|
|
25
|
-
CODEBLOCK_DATA_PATH = os.path.join(os.path.dirname(__file__), 'data/data.json')
|
|
26
19
|
|
|
27
20
|
VARIABLE_TYPES = {'txt', 'comp', 'num', 'item', 'loc', 'var', 'snd', 'part', 'pot', 'g_val', 'vec', 'pn_el'}
|
|
28
21
|
TEMPLATE_STARTERS = {'event', 'entity_event', 'func', 'process'}
|
|
@@ -31,9 +24,6 @@ SINGLE_NAME_CODEBLOCKS = {'func', 'process', 'call_func', 'start_process', 'else
|
|
|
31
24
|
TARGETS = ['Selection', 'Default', 'Killer', 'Damager', 'Shooter', 'Victim', 'AllPlayers', 'Projectile', 'AllEntities', 'AllMobs', 'LastEntity']
|
|
32
25
|
TARGET_CODEBLOCKS = {'player_action', 'entity_action', 'if_player', 'if_entity'}
|
|
33
26
|
|
|
34
|
-
VAR_SHORTHAND_CHAR = '$'
|
|
35
|
-
VAR_SCOPES = {'g': 'unsaved', 's': 'saved', 'l': 'local', 'i': 'line'}
|
|
36
|
-
|
|
37
27
|
CODECLIENT_URL = 'ws://localhost:31375'
|
|
38
28
|
|
|
39
29
|
|
|
@@ -57,54 +47,59 @@ DEFAULT_TARGET = Target.SELECTION
|
|
|
57
47
|
|
|
58
48
|
|
|
59
49
|
class CodeBlock:
|
|
60
|
-
def __init__(self, name: str, args: Tuple=(), target: Target=DEFAULT_TARGET, data:
|
|
50
|
+
def __init__(self, name: str, args: Tuple=(), target: Target=DEFAULT_TARGET, data: dict={}, tags: dict[str, str]={}):
|
|
61
51
|
self.name = name
|
|
62
52
|
self.args = args
|
|
63
53
|
self.target = target
|
|
64
54
|
self.data = data
|
|
55
|
+
self.tags = tags
|
|
65
56
|
|
|
66
57
|
def __repr__(self) -> str:
|
|
67
58
|
if self.name in SINGLE_NAME_CODEBLOCKS:
|
|
68
59
|
if self.name == 'else':
|
|
69
60
|
return 'CodeBlock(else)'
|
|
70
61
|
return f'CodeBlock({self.name}, {self.data["data"]})'
|
|
71
|
-
|
|
62
|
+
if 'block' in self.data:
|
|
72
63
|
return f'CodeBlock({self.data["block"]}, {self.name})'
|
|
73
64
|
return f'CodeBlock(bracket, {self.data["type"]}, {self.data["direct"]})'
|
|
74
65
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
66
|
+
def build(self, include_tags: bool=True) -> dict:
|
|
67
|
+
"""
|
|
68
|
+
Builds a properly formatted block from a CodeBlock object.
|
|
69
|
+
"""
|
|
70
|
+
built_block = self.data.copy()
|
|
71
|
+
codeblock_type = self.data.get('block')
|
|
72
|
+
|
|
73
|
+
# add target if necessary ('Selection' is the default when 'target' is blank)
|
|
74
|
+
if codeblock_type in TARGET_CODEBLOCKS and self.target != DEFAULT_TARGET:
|
|
75
|
+
built_block['target'] = self.target.get_string_value()
|
|
76
|
+
|
|
77
|
+
# add items into args
|
|
78
|
+
final_args = [arg.format(slot) for slot, arg in enumerate(self.args) if arg.type in VARIABLE_TYPES]
|
|
79
|
+
|
|
80
|
+
# check for unrecognized name, add tags
|
|
81
|
+
if codeblock_type is not None: # for brackets
|
|
82
|
+
if self.name not in CODEBLOCK_DATA[codeblock_type]:
|
|
83
|
+
_warn_unrecognized_name(codeblock_type, self.name)
|
|
84
|
+
elif include_tags:
|
|
85
|
+
tags = _get_codeblock_tags(codeblock_type, self.name, self.tags)
|
|
86
|
+
if len(final_args) + len(tags) > 27:
|
|
87
|
+
final_args = final_args[:(27-len(tags))] # trim list if over 27 elements
|
|
88
|
+
final_args.extend(tags) # add tags to end
|
|
89
|
+
|
|
90
|
+
# if final_args:
|
|
91
|
+
built_block['args'] = {'items': final_args}
|
|
92
|
+
return built_block
|
|
78
93
|
|
|
79
94
|
|
|
80
95
|
def _warn_unrecognized_name(codeblock_type: str, codeblock_name: str):
|
|
81
|
-
close = get_close_matches(codeblock_name,
|
|
96
|
+
close = get_close_matches(codeblock_name, CODEBLOCK_DATA[codeblock_type].keys())
|
|
82
97
|
if close:
|
|
83
|
-
|
|
98
|
+
warn(f'Code block name "{codeblock_name}" not recognized. Did you mean "{close[0]}"?')
|
|
84
99
|
else:
|
|
85
|
-
|
|
100
|
+
warn(f'Code block name "{codeblock_name}" not recognized. Try spell checking or retyping without spaces.')
|
|
86
101
|
|
|
87
102
|
|
|
88
|
-
def _load_codeblock_data() -> Tuple:
|
|
89
|
-
tag_data = {}
|
|
90
|
-
if os.path.exists(CODEBLOCK_DATA_PATH):
|
|
91
|
-
with open(CODEBLOCK_DATA_PATH, 'r') as f:
|
|
92
|
-
tag_data = json.load(f)
|
|
93
|
-
else:
|
|
94
|
-
_warn('data.json not found -- Item tags and error checking will not work.')
|
|
95
|
-
return ({}, set(), set())
|
|
96
|
-
|
|
97
|
-
del tag_data['meta']
|
|
98
|
-
|
|
99
|
-
all_names = [x for l in [d.keys() for d in tag_data.values()] for x in l] # flatten list
|
|
100
|
-
return (
|
|
101
|
-
tag_data,
|
|
102
|
-
set(tag_data['extras'].keys()),
|
|
103
|
-
set(all_names)
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
TAGDATA, TAGDATA_EXTRAS_KEYS, ALL_CODEBLOCK_NAMES = _load_codeblock_data()
|
|
107
|
-
|
|
108
103
|
def _add_inverted(data, inverted):
|
|
109
104
|
"""
|
|
110
105
|
If inverted is true, add 'inverted': 'NOT' to data.
|
|
@@ -113,36 +108,48 @@ def _add_inverted(data, inverted):
|
|
|
113
108
|
data['inverted'] = 'NOT'
|
|
114
109
|
|
|
115
110
|
|
|
116
|
-
def
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
111
|
+
def _convert_args(args):
|
|
112
|
+
return tuple(map(convert_argument, args))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _check_applied_tags(tags: list[dict], applied_tags: dict[str, str], codeblock_name: str) -> dict[str, str]:
|
|
116
|
+
if len(applied_tags) > 0 and len(tags) == 0:
|
|
117
|
+
warn(f'Action "{codeblock_name}" does not have any tags, but still received {len(applied_tags)}.')
|
|
118
|
+
return {}
|
|
119
|
+
valid_tags = {}
|
|
120
|
+
tags_formatted = {t['name']: t for t in tags}
|
|
121
|
+
for name, option in applied_tags.items():
|
|
122
|
+
if name not in tags_formatted:
|
|
123
|
+
tag_names_joined = '\n'.join(map(lambda s: ' - '+s, tags_formatted.keys()))
|
|
124
|
+
warn(f'Tag "{name}" does not exist for action "{codeblock_name}". Available tags:\n{tag_names_joined}')
|
|
125
|
+
elif option not in tags_formatted[name]['options']:
|
|
126
|
+
options_joined = '\n'.join(map(lambda s: ' - '+s, tags_formatted[name]['options']))
|
|
127
|
+
warn(f'Tag "{name}" does not have the option "{option}". Available tag options:\n{options_joined}')
|
|
127
128
|
else:
|
|
128
|
-
|
|
129
|
-
return
|
|
129
|
+
valid_tags[name] = option
|
|
130
|
+
return valid_tags
|
|
130
131
|
|
|
131
132
|
|
|
132
|
-
def _reformat_codeblock_tags(tags, codeblock_type: str, codeblock_name: str):
|
|
133
|
+
def _reformat_codeblock_tags(tags: list[dict], codeblock_type: str, codeblock_name: str, applied_tags: dict[str, str]):
|
|
133
134
|
"""
|
|
134
|
-
Turns
|
|
135
|
+
Turns tag objects into DiamondFire formatted tag items
|
|
135
136
|
"""
|
|
137
|
+
|
|
138
|
+
valid_applied_tags = _check_applied_tags(tags, applied_tags, codeblock_name)
|
|
136
139
|
reformatted_tags = []
|
|
137
140
|
for tag_item in tags:
|
|
138
|
-
|
|
141
|
+
tag_name = tag_item['name']
|
|
142
|
+
tag_option = tag_item['default']
|
|
143
|
+
if tag_name in valid_applied_tags:
|
|
144
|
+
tag_option = valid_applied_tags[tag_name]
|
|
145
|
+
|
|
139
146
|
new_tag_item = {
|
|
140
147
|
'item': {
|
|
141
148
|
'id': 'bl_tag',
|
|
142
149
|
'data': {
|
|
143
|
-
'option':
|
|
144
|
-
'tag':
|
|
145
|
-
'action':
|
|
150
|
+
'option': tag_option,
|
|
151
|
+
'tag': tag_name,
|
|
152
|
+
'action': codeblock_name,
|
|
146
153
|
'block': codeblock_type
|
|
147
154
|
}
|
|
148
155
|
},
|
|
@@ -152,56 +159,15 @@ def _reformat_codeblock_tags(tags, codeblock_type: str, codeblock_name: str):
|
|
|
152
159
|
return reformatted_tags
|
|
153
160
|
|
|
154
161
|
|
|
155
|
-
def _get_codeblock_tags(codeblock_type: str, codeblock_name: str):
|
|
162
|
+
def _get_codeblock_tags(codeblock_type: str, codeblock_name: str, applied_tags: dict[str, str]):
|
|
156
163
|
"""
|
|
157
164
|
Get tags for the specified codeblock type and name
|
|
158
165
|
"""
|
|
159
|
-
|
|
160
|
-
if
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return _reformat_codeblock_tags(tags, codeblock_type, codeblock_name)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
def _build_block(codeblock: CodeBlock, include_tags: bool):
|
|
168
|
-
"""
|
|
169
|
-
Builds a properly formatted block from a CodeBlock object.
|
|
170
|
-
"""
|
|
171
|
-
built_block = codeblock.data.copy()
|
|
172
|
-
codeblock_type = codeblock.data.get('block')
|
|
173
|
-
|
|
174
|
-
# add target if necessary ('Selection' is the default when 'target' is blank)
|
|
175
|
-
if codeblock_type in TARGET_CODEBLOCKS and codeblock.target != DEFAULT_TARGET:
|
|
176
|
-
built_block['target'] = codeblock.target.get_string_value()
|
|
177
|
-
|
|
178
|
-
# add items into args
|
|
179
|
-
final_args = [arg.format(slot) for slot, arg in enumerate(codeblock.args) if arg.type in VARIABLE_TYPES]
|
|
180
|
-
|
|
181
|
-
# check for unrecognized name, add tags
|
|
182
|
-
if codeblock_type is not None: # for brackets
|
|
183
|
-
if codeblock_type not in TAGDATA_EXTRAS_KEYS and codeblock.name not in ALL_CODEBLOCK_NAMES:
|
|
184
|
-
_warn_unrecognized_name(codeblock_type, codeblock.name)
|
|
185
|
-
elif include_tags:
|
|
186
|
-
tags = _get_codeblock_tags(codeblock_type, codeblock.name)
|
|
187
|
-
if len(final_args) + len(tags) > 27:
|
|
188
|
-
final_args = final_args[:(27-len(tags))] # trim list if over 27 elements
|
|
189
|
-
final_args.extend(tags) # add tags to end
|
|
190
|
-
|
|
191
|
-
built_block['args'] = {'items': final_args}
|
|
192
|
-
return built_block
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def _df_encode(json_string: str) -> str:
|
|
196
|
-
"""
|
|
197
|
-
Encodes a stringified json.
|
|
198
|
-
"""
|
|
199
|
-
encoded_string = gzip.compress(json_string.encode('utf-8'))
|
|
200
|
-
return base64.b64encode(encoded_string).decode('utf-8')
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
def _df_decode(encoded_string: str) -> str:
|
|
204
|
-
return gzip.decompress(base64.b64decode(encoded_string)).decode('utf-8')
|
|
166
|
+
action_data = CODEBLOCK_DATA[codeblock_type][codeblock_name]
|
|
167
|
+
if 'deprecatedNote' in action_data:
|
|
168
|
+
warn(f'Action "{codeblock_name}" is deprecated: {action_data["deprecatedNote"]}')
|
|
169
|
+
tags = action_data['tags']
|
|
170
|
+
return _reformat_codeblock_tags(tags, codeblock_type, codeblock_name, applied_tags)
|
|
205
171
|
|
|
206
172
|
|
|
207
173
|
def _get_template_item(template_code: str, name: str, author: str) -> NbtItem:
|
|
@@ -231,7 +197,7 @@ class DFTemplate:
|
|
|
231
197
|
Represents a DiamondFire code template.
|
|
232
198
|
"""
|
|
233
199
|
def __init__(self, name: str=None, author: str='pyre'):
|
|
234
|
-
self.codeblocks:
|
|
200
|
+
self.codeblocks: list[CodeBlock] = []
|
|
235
201
|
self.bracket_stack: list[str] = []
|
|
236
202
|
self.name = name
|
|
237
203
|
self.author = author
|
|
@@ -246,12 +212,16 @@ class DFTemplate:
|
|
|
246
212
|
"""
|
|
247
213
|
Create a template object from an existing template code.
|
|
248
214
|
"""
|
|
249
|
-
template_dict = json.loads(
|
|
215
|
+
template_dict = json.loads(df_decode(template_code))
|
|
250
216
|
template = DFTemplate()
|
|
251
217
|
for block_dict in template_dict['blocks']:
|
|
218
|
+
block_tags = get_default_tags(block_dict.get('block'), block_dict.get('action'))
|
|
252
219
|
if 'args' in block_dict:
|
|
253
220
|
args = []
|
|
254
221
|
for item_dict in block_dict['args']['items']:
|
|
222
|
+
if item_dict['item'].get('id') == 'bl_tag':
|
|
223
|
+
tag_data = item_dict['item']['data']
|
|
224
|
+
block_tags[tag_data['tag']] = tag_data['option']
|
|
255
225
|
parsed_item = item_from_dict(item_dict['item'])
|
|
256
226
|
if parsed_item is not None:
|
|
257
227
|
args.append(parsed_item)
|
|
@@ -262,7 +232,11 @@ class DFTemplate:
|
|
|
262
232
|
codeblock_name = block_dict['block']
|
|
263
233
|
elif 'action' in block_dict:
|
|
264
234
|
codeblock_name = block_dict['action']
|
|
265
|
-
|
|
235
|
+
|
|
236
|
+
if codeblock_name == 'bracket' or block_dict['block'] == 'else':
|
|
237
|
+
codeblock = CodeBlock(codeblock_name, data=block_dict)
|
|
238
|
+
else:
|
|
239
|
+
codeblock = CodeBlock(codeblock_name, args, target, block_dict, tags=block_tags)
|
|
266
240
|
template.codeblocks.append(codeblock)
|
|
267
241
|
|
|
268
242
|
return template
|
|
@@ -296,16 +270,16 @@ class DFTemplate:
|
|
|
296
270
|
:param bool include_tags: If True, include item tags in code blocks. Otherwise omit them.
|
|
297
271
|
:return: String containing encoded template data.
|
|
298
272
|
"""
|
|
299
|
-
template_dict_blocks = [
|
|
273
|
+
template_dict_blocks = [codeblock.build(include_tags) for codeblock in self.codeblocks]
|
|
300
274
|
template_dict = {'blocks': template_dict_blocks}
|
|
301
275
|
first_block = template_dict_blocks[0]
|
|
302
276
|
if first_block['block'] not in TEMPLATE_STARTERS:
|
|
303
|
-
|
|
277
|
+
warn('Template does not start with an event, function, or process.')
|
|
304
278
|
|
|
305
279
|
self._set_template_name(first_block)
|
|
306
280
|
|
|
307
281
|
json_string = json.dumps(template_dict, separators=(',', ':'))
|
|
308
|
-
return
|
|
282
|
+
return df_encode(json_string)
|
|
309
283
|
|
|
310
284
|
|
|
311
285
|
def build_and_send(self, method: Literal['recode', 'codeclient'], include_tags: bool=True) -> int:
|
|
@@ -350,78 +324,79 @@ class DFTemplate:
|
|
|
350
324
|
self._add_codeblock(cmd, index)
|
|
351
325
|
|
|
352
326
|
|
|
353
|
-
def function(self, name: str, *args, index: int|None=None):
|
|
354
|
-
args =
|
|
355
|
-
cmd = CodeBlock('
|
|
327
|
+
def function(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
328
|
+
args = _convert_args(args)
|
|
329
|
+
cmd = CodeBlock('dynamic', args, data={'id': 'block', 'block': 'func', 'data': name}, tags=tags)
|
|
356
330
|
self._add_codeblock(cmd, index)
|
|
357
331
|
|
|
358
332
|
|
|
359
|
-
def process(self, name: str, *args, index: int|None=None):
|
|
360
|
-
args =
|
|
361
|
-
cmd = CodeBlock('
|
|
333
|
+
def process(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
334
|
+
args = _convert_args(args)
|
|
335
|
+
cmd = CodeBlock('dynamic', args, data={'id': 'block', 'block': 'process', 'data': name}, tags=tags)
|
|
362
336
|
self._add_codeblock(cmd, index)
|
|
363
337
|
|
|
364
338
|
|
|
365
339
|
def call_function(self, name: str, *args, index: int|None=None):
|
|
366
|
-
args =
|
|
367
|
-
cmd = CodeBlock('
|
|
340
|
+
args = _convert_args(args)
|
|
341
|
+
cmd = CodeBlock('dynamic', args, data={'id': 'block', 'block': 'call_func', 'data': name})
|
|
368
342
|
self._add_codeblock(cmd, index)
|
|
369
343
|
|
|
370
|
-
|
|
371
|
-
|
|
344
|
+
|
|
345
|
+
def start_process(self, name: str, tags: dict[str, str]={}, index: int|None=None):
|
|
346
|
+
cmd = CodeBlock('dynamic', data={'id': 'block', 'block': 'start_process', 'data': name}, tags=tags)
|
|
372
347
|
self._add_codeblock(cmd, index)
|
|
373
348
|
|
|
374
349
|
|
|
375
|
-
def player_action(self, name: str, *args, target: Target=DEFAULT_TARGET, index: int|None=None):
|
|
376
|
-
args =
|
|
377
|
-
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'player_action', 'action': name})
|
|
350
|
+
def player_action(self, name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, index: int|None=None):
|
|
351
|
+
args = _convert_args(args)
|
|
352
|
+
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'player_action', 'action': name}, tags=tags)
|
|
378
353
|
self._add_codeblock(cmd, index)
|
|
379
354
|
|
|
380
355
|
|
|
381
|
-
def game_action(self, name: str, *args, index: int|None=None):
|
|
382
|
-
args =
|
|
383
|
-
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'game_action', 'action': name})
|
|
356
|
+
def game_action(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
357
|
+
args = _convert_args(args)
|
|
358
|
+
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'game_action', 'action': name}, tags=tags)
|
|
384
359
|
self._add_codeblock(cmd, index)
|
|
385
360
|
|
|
386
361
|
|
|
387
|
-
def entity_action(self, name: str, *args, target: Target=DEFAULT_TARGET, index: int|None=None):
|
|
388
|
-
args =
|
|
389
|
-
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'entity_action', 'action': name})
|
|
362
|
+
def entity_action(self, name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, index: int|None=None):
|
|
363
|
+
args = _convert_args(args)
|
|
364
|
+
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'entity_action', 'action': name}, tags=tags)
|
|
390
365
|
self._add_codeblock(cmd, index)
|
|
391
366
|
|
|
392
367
|
|
|
393
|
-
def if_player(self, name: str, *args, target: Target=DEFAULT_TARGET, inverted: bool=False, index: int|None=None):
|
|
394
|
-
args =
|
|
368
|
+
def if_player(self, name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
|
|
369
|
+
args = _convert_args(args)
|
|
395
370
|
data = {'id': 'block', 'block': 'if_player', 'action': name}
|
|
396
371
|
_add_inverted(data, inverted)
|
|
397
|
-
cmd = CodeBlock(name, args, target=target, data=data)
|
|
372
|
+
cmd = CodeBlock(name, args, target=target, data=data, tags=tags)
|
|
398
373
|
self._add_codeblock(cmd, index)
|
|
399
374
|
self._openbracket(index)
|
|
400
375
|
|
|
401
376
|
|
|
402
|
-
def if_variable(self, name: str, *args, inverted: bool=False, index: int|None=None):
|
|
403
|
-
args =
|
|
377
|
+
def if_variable(self, name: str, *args, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
|
|
378
|
+
args = _convert_args(args)
|
|
404
379
|
data = {'id': 'block', 'block': 'if_var', 'action': name}
|
|
405
380
|
_add_inverted(data, inverted)
|
|
406
|
-
cmd = CodeBlock(name, args, data=data)
|
|
381
|
+
cmd = CodeBlock(name, args, data=data, tags=tags)
|
|
407
382
|
self._add_codeblock(cmd, index)
|
|
408
383
|
self._openbracket(index)
|
|
409
384
|
|
|
410
385
|
|
|
411
|
-
def if_game(self, name: str, *args, inverted: bool=False, index: int|None=None):
|
|
412
|
-
args =
|
|
386
|
+
def if_game(self, name: str, *args, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
|
|
387
|
+
args = _convert_args(args)
|
|
413
388
|
data = {'id': 'block', 'block': 'if_game', 'action': name}
|
|
414
389
|
_add_inverted(data, inverted)
|
|
415
|
-
cmd = CodeBlock(name, args, data=data)
|
|
390
|
+
cmd = CodeBlock(name, args, data=data, tags=tags)
|
|
416
391
|
self._add_codeblock(cmd, index)
|
|
417
392
|
self._openbracket(index)
|
|
418
393
|
|
|
419
394
|
|
|
420
|
-
def if_entity(self, name: str, *args, target: Target=DEFAULT_TARGET, inverted: bool=False, index: int|None=None):
|
|
421
|
-
args =
|
|
395
|
+
def if_entity(self, name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
|
|
396
|
+
args = _convert_args(args)
|
|
422
397
|
data = {'id': 'block', 'block': 'if_entity', 'action': name}
|
|
423
398
|
_add_inverted(data, inverted)
|
|
424
|
-
cmd = CodeBlock(name, args, target=target, data=data)
|
|
399
|
+
cmd = CodeBlock(name, args, target=target, data=data, tags=tags)
|
|
425
400
|
self._add_codeblock(cmd, index)
|
|
426
401
|
self._openbracket(index)
|
|
427
402
|
|
|
@@ -432,37 +407,37 @@ class DFTemplate:
|
|
|
432
407
|
self._openbracket(index)
|
|
433
408
|
|
|
434
409
|
|
|
435
|
-
def repeat(self, name: str, *args, sub_action: str=None, index: int|None=None):
|
|
436
|
-
args =
|
|
410
|
+
def repeat(self, name: str, *args, tags: dict[str, str]={}, sub_action: str=None, index: int|None=None):
|
|
411
|
+
args = _convert_args(args)
|
|
437
412
|
data = {'id': 'block', 'block': 'repeat', 'action': name}
|
|
438
413
|
if sub_action is not None:
|
|
439
414
|
data['subAction'] = sub_action
|
|
440
|
-
cmd = CodeBlock(name, args, data=data)
|
|
415
|
+
cmd = CodeBlock(name, args, data=data, tags=tags)
|
|
441
416
|
self._add_codeblock(cmd, index)
|
|
442
417
|
self._openbracket(index, 'repeat')
|
|
443
418
|
|
|
444
419
|
|
|
445
420
|
def bracket(self, *args, index: int|None=None):
|
|
446
|
-
args =
|
|
421
|
+
args = _convert_args(args)
|
|
447
422
|
cmd = CodeBlock('bracket', data={'id': 'bracket', 'direct': 'close', 'type': self.bracket_stack.pop()})
|
|
448
423
|
self._add_codeblock(cmd, index)
|
|
449
424
|
|
|
450
425
|
|
|
451
|
-
def control(self, name: str, *args, index: int|None=None):
|
|
452
|
-
args =
|
|
453
|
-
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'control', 'action': name})
|
|
426
|
+
def control(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
427
|
+
args = _convert_args(args)
|
|
428
|
+
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'control', 'action': name}, tags=tags)
|
|
454
429
|
self._add_codeblock(cmd, index)
|
|
455
430
|
|
|
456
431
|
|
|
457
|
-
def select_object(self, name: str, *args, index: int|None=None):
|
|
458
|
-
args =
|
|
459
|
-
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'select_obj', 'action': name})
|
|
432
|
+
def select_object(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
433
|
+
args = _convert_args(args)
|
|
434
|
+
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'select_obj', 'action': name}, tags=tags)
|
|
460
435
|
self._add_codeblock(cmd, index)
|
|
461
436
|
|
|
462
437
|
|
|
463
|
-
def set_variable(self, name: str, *args, index: int|None=None):
|
|
464
|
-
args =
|
|
465
|
-
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'set_var', 'action': name})
|
|
438
|
+
def set_variable(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
439
|
+
args = _convert_args(args)
|
|
440
|
+
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'set_var', 'action': name}, tags=tags)
|
|
466
441
|
self._add_codeblock(cmd, index)
|
|
467
442
|
|
|
468
443
|
|
|
@@ -476,6 +451,6 @@ class DFTemplate:
|
|
|
476
451
|
:param bool var_shorthand: If True, all variables will be written using variable shorthand.
|
|
477
452
|
"""
|
|
478
453
|
flags = GeneratorFlags(indent_size, literal_shorthand, var_shorthand)
|
|
479
|
-
with open(output_path, 'w') as f:
|
|
454
|
+
with open(output_path, 'w', encoding='utf-8') as f:
|
|
480
455
|
f.write(generate_script(self, flags))
|
|
481
456
|
|