dfpyre 0.6.3__py3-none-any.whl → 0.7.1__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 +77 -0
- dfpyre/data/actiondump_min.json +1 -0
- dfpyre/items.py +22 -8
- dfpyre/pyre.py +139 -167
- dfpyre/scriptgen.py +10 -4
- dfpyre/util.py +28 -0
- {dfpyre-0.6.3.dist-info → dfpyre-0.7.1.dist-info}/METADATA +16 -3
- dfpyre-0.7.1.dist-info/RECORD +12 -0
- dfpyre/data/data.json +0 -1
- dfpyre-0.6.3.dist-info/RECORD +0 -10
- {dfpyre-0.6.3.dist-info → dfpyre-0.7.1.dist-info}/LICENSE +0 -0
- {dfpyre-0.6.3.dist-info → dfpyre-0.7.1.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
|
|
|
@@ -274,7 +283,7 @@ class parameter:
|
|
|
274
283
|
self.optional = optional
|
|
275
284
|
self.description = description
|
|
276
285
|
self.note = note
|
|
277
|
-
self.default_value = default_value
|
|
286
|
+
self.default_value = convert_argument(default_value)
|
|
278
287
|
|
|
279
288
|
|
|
280
289
|
def format(self, slot: int):
|
|
@@ -292,8 +301,13 @@ class parameter:
|
|
|
292
301
|
formatted_dict['item']['data']['description'] = self.description
|
|
293
302
|
if self.note:
|
|
294
303
|
formatted_dict['item']['data']['note'] = self.note
|
|
295
|
-
if self.default_value is not None
|
|
296
|
-
|
|
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']
|
|
297
311
|
|
|
298
312
|
return formatted_dict
|
|
299
313
|
|
|
@@ -311,7 +325,7 @@ def _some_or(value: Any, none_value: Any):
|
|
|
311
325
|
return value
|
|
312
326
|
|
|
313
327
|
|
|
314
|
-
def item_from_dict(item_dict:
|
|
328
|
+
def item_from_dict(item_dict: dict) -> object:
|
|
315
329
|
item_id = item_dict['id']
|
|
316
330
|
item_data = item_dict['data']
|
|
317
331
|
|
dfpyre/pyre.py
CHANGED
|
@@ -4,36 +4,26 @@ 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'}
|
|
29
|
-
|
|
22
|
+
DYNAMIC_CODEBLOCKS = {'func', 'process', 'call_func', 'start_process'}
|
|
30
23
|
|
|
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
|
-
if self.name in
|
|
58
|
+
if self.name in DYNAMIC_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,57 +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
|
-
if final_args:
|
|
192
|
-
built_block['args'] = {'items': final_args}
|
|
193
|
-
return built_block
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def _df_encode(json_string: str) -> str:
|
|
197
|
-
"""
|
|
198
|
-
Encodes a stringified json.
|
|
199
|
-
"""
|
|
200
|
-
encoded_string = gzip.compress(json_string.encode('utf-8'))
|
|
201
|
-
return base64.b64encode(encoded_string).decode('utf-8')
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def _df_decode(encoded_string: str) -> str:
|
|
205
|
-
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)
|
|
206
171
|
|
|
207
172
|
|
|
208
173
|
def _get_template_item(template_code: str, name: str, author: str) -> NbtItem:
|
|
@@ -232,7 +197,7 @@ class DFTemplate:
|
|
|
232
197
|
Represents a DiamondFire code template.
|
|
233
198
|
"""
|
|
234
199
|
def __init__(self, name: str=None, author: str='pyre'):
|
|
235
|
-
self.codeblocks:
|
|
200
|
+
self.codeblocks: list[CodeBlock] = []
|
|
236
201
|
self.bracket_stack: list[str] = []
|
|
237
202
|
self.name = name
|
|
238
203
|
self.author = author
|
|
@@ -247,27 +212,33 @@ class DFTemplate:
|
|
|
247
212
|
"""
|
|
248
213
|
Create a template object from an existing template code.
|
|
249
214
|
"""
|
|
250
|
-
template_dict = json.loads(
|
|
215
|
+
template_dict = json.loads(df_decode(template_code))
|
|
251
216
|
template = DFTemplate()
|
|
252
217
|
for block_dict in template_dict['blocks']:
|
|
218
|
+
block_tags = get_default_tags(block_dict.get('block'), block_dict.get('action'))
|
|
253
219
|
if 'args' in block_dict:
|
|
254
220
|
args = []
|
|
255
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']
|
|
256
225
|
parsed_item = item_from_dict(item_dict['item'])
|
|
257
226
|
if parsed_item is not None:
|
|
258
227
|
args.append(parsed_item)
|
|
259
228
|
target = Target(TARGETS.index(block_dict['target'])) if 'target' in block_dict else DEFAULT_TARGET
|
|
260
229
|
|
|
261
|
-
|
|
262
|
-
if 'block'
|
|
263
|
-
|
|
230
|
+
codeblock_action = 'bracket'
|
|
231
|
+
if block_dict.get('block') == 'else':
|
|
232
|
+
codeblock_action = 'else'
|
|
233
|
+
elif block_dict.get('block') in DYNAMIC_CODEBLOCKS:
|
|
234
|
+
codeblock_action = 'dynamic'
|
|
264
235
|
elif 'action' in block_dict:
|
|
265
|
-
|
|
236
|
+
codeblock_action = block_dict['action']
|
|
266
237
|
|
|
267
|
-
if
|
|
268
|
-
codeblock = CodeBlock(
|
|
238
|
+
if codeblock_action == 'bracket' or block_dict['block'] == 'else':
|
|
239
|
+
codeblock = CodeBlock(codeblock_action, data=block_dict)
|
|
269
240
|
else:
|
|
270
|
-
codeblock = CodeBlock(
|
|
241
|
+
codeblock = CodeBlock(codeblock_action, args, target, block_dict, tags=block_tags)
|
|
271
242
|
template.codeblocks.append(codeblock)
|
|
272
243
|
|
|
273
244
|
return template
|
|
@@ -301,16 +272,16 @@ class DFTemplate:
|
|
|
301
272
|
:param bool include_tags: If True, include item tags in code blocks. Otherwise omit them.
|
|
302
273
|
:return: String containing encoded template data.
|
|
303
274
|
"""
|
|
304
|
-
template_dict_blocks = [
|
|
275
|
+
template_dict_blocks = [codeblock.build(include_tags) for codeblock in self.codeblocks]
|
|
305
276
|
template_dict = {'blocks': template_dict_blocks}
|
|
306
277
|
first_block = template_dict_blocks[0]
|
|
307
278
|
if first_block['block'] not in TEMPLATE_STARTERS:
|
|
308
|
-
|
|
279
|
+
warn('Template does not start with an event, function, or process.')
|
|
309
280
|
|
|
310
281
|
self._set_template_name(first_block)
|
|
311
282
|
|
|
312
283
|
json_string = json.dumps(template_dict, separators=(',', ':'))
|
|
313
|
-
return
|
|
284
|
+
return df_encode(json_string)
|
|
314
285
|
|
|
315
286
|
|
|
316
287
|
def build_and_send(self, method: Literal['recode', 'codeclient'], include_tags: bool=True) -> int:
|
|
@@ -355,78 +326,79 @@ class DFTemplate:
|
|
|
355
326
|
self._add_codeblock(cmd, index)
|
|
356
327
|
|
|
357
328
|
|
|
358
|
-
def function(self, name: str, *args, index: int|None=None):
|
|
359
|
-
args =
|
|
360
|
-
cmd = CodeBlock('
|
|
329
|
+
def function(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
330
|
+
args = _convert_args(args)
|
|
331
|
+
cmd = CodeBlock('dynamic', args, data={'id': 'block', 'block': 'func', 'data': name}, tags=tags)
|
|
361
332
|
self._add_codeblock(cmd, index)
|
|
362
333
|
|
|
363
334
|
|
|
364
|
-
def process(self, name: str, *args, index: int|None=None):
|
|
365
|
-
args =
|
|
366
|
-
cmd = CodeBlock('
|
|
335
|
+
def process(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
336
|
+
args = _convert_args(args)
|
|
337
|
+
cmd = CodeBlock('dynamic', args, data={'id': 'block', 'block': 'process', 'data': name}, tags=tags)
|
|
367
338
|
self._add_codeblock(cmd, index)
|
|
368
339
|
|
|
369
340
|
|
|
370
341
|
def call_function(self, name: str, *args, index: int|None=None):
|
|
371
|
-
args =
|
|
372
|
-
cmd = CodeBlock('
|
|
342
|
+
args = _convert_args(args)
|
|
343
|
+
cmd = CodeBlock('dynamic', args, data={'id': 'block', 'block': 'call_func', 'data': name})
|
|
373
344
|
self._add_codeblock(cmd, index)
|
|
374
345
|
|
|
375
|
-
|
|
376
|
-
|
|
346
|
+
|
|
347
|
+
def start_process(self, name: str, tags: dict[str, str]={}, index: int|None=None):
|
|
348
|
+
cmd = CodeBlock('dynamic', data={'id': 'block', 'block': 'start_process', 'data': name}, tags=tags)
|
|
377
349
|
self._add_codeblock(cmd, index)
|
|
378
350
|
|
|
379
351
|
|
|
380
|
-
def player_action(self, name: str, *args, target: Target=DEFAULT_TARGET, index: int|None=None):
|
|
381
|
-
args =
|
|
382
|
-
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'player_action', 'action': name})
|
|
352
|
+
def player_action(self, name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, index: int|None=None):
|
|
353
|
+
args = _convert_args(args)
|
|
354
|
+
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'player_action', 'action': name}, tags=tags)
|
|
383
355
|
self._add_codeblock(cmd, index)
|
|
384
356
|
|
|
385
357
|
|
|
386
|
-
def game_action(self, name: str, *args, index: int|None=None):
|
|
387
|
-
args =
|
|
388
|
-
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'game_action', 'action': name})
|
|
358
|
+
def game_action(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
359
|
+
args = _convert_args(args)
|
|
360
|
+
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'game_action', 'action': name}, tags=tags)
|
|
389
361
|
self._add_codeblock(cmd, index)
|
|
390
362
|
|
|
391
363
|
|
|
392
|
-
def entity_action(self, name: str, *args, target: Target=DEFAULT_TARGET, index: int|None=None):
|
|
393
|
-
args =
|
|
394
|
-
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'entity_action', 'action': name})
|
|
364
|
+
def entity_action(self, name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, index: int|None=None):
|
|
365
|
+
args = _convert_args(args)
|
|
366
|
+
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'entity_action', 'action': name}, tags=tags)
|
|
395
367
|
self._add_codeblock(cmd, index)
|
|
396
368
|
|
|
397
369
|
|
|
398
|
-
def if_player(self, name: str, *args, target: Target=DEFAULT_TARGET, inverted: bool=False, index: int|None=None):
|
|
399
|
-
args =
|
|
370
|
+
def if_player(self, name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
|
|
371
|
+
args = _convert_args(args)
|
|
400
372
|
data = {'id': 'block', 'block': 'if_player', 'action': name}
|
|
401
373
|
_add_inverted(data, inverted)
|
|
402
|
-
cmd = CodeBlock(name, args, target=target, data=data)
|
|
374
|
+
cmd = CodeBlock(name, args, target=target, data=data, tags=tags)
|
|
403
375
|
self._add_codeblock(cmd, index)
|
|
404
376
|
self._openbracket(index)
|
|
405
377
|
|
|
406
378
|
|
|
407
|
-
def if_variable(self, name: str, *args, inverted: bool=False, index: int|None=None):
|
|
408
|
-
args =
|
|
379
|
+
def if_variable(self, name: str, *args, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
|
|
380
|
+
args = _convert_args(args)
|
|
409
381
|
data = {'id': 'block', 'block': 'if_var', 'action': name}
|
|
410
382
|
_add_inverted(data, inverted)
|
|
411
|
-
cmd = CodeBlock(name, args, data=data)
|
|
383
|
+
cmd = CodeBlock(name, args, data=data, tags=tags)
|
|
412
384
|
self._add_codeblock(cmd, index)
|
|
413
385
|
self._openbracket(index)
|
|
414
386
|
|
|
415
387
|
|
|
416
|
-
def if_game(self, name: str, *args, inverted: bool=False, index: int|None=None):
|
|
417
|
-
args =
|
|
388
|
+
def if_game(self, name: str, *args, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
|
|
389
|
+
args = _convert_args(args)
|
|
418
390
|
data = {'id': 'block', 'block': 'if_game', 'action': name}
|
|
419
391
|
_add_inverted(data, inverted)
|
|
420
|
-
cmd = CodeBlock(name, args, data=data)
|
|
392
|
+
cmd = CodeBlock(name, args, data=data, tags=tags)
|
|
421
393
|
self._add_codeblock(cmd, index)
|
|
422
394
|
self._openbracket(index)
|
|
423
395
|
|
|
424
396
|
|
|
425
|
-
def if_entity(self, name: str, *args, target: Target=DEFAULT_TARGET, inverted: bool=False, index: int|None=None):
|
|
426
|
-
args =
|
|
397
|
+
def if_entity(self, name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
|
|
398
|
+
args = _convert_args(args)
|
|
427
399
|
data = {'id': 'block', 'block': 'if_entity', 'action': name}
|
|
428
400
|
_add_inverted(data, inverted)
|
|
429
|
-
cmd = CodeBlock(name, args, target=target, data=data)
|
|
401
|
+
cmd = CodeBlock(name, args, target=target, data=data, tags=tags)
|
|
430
402
|
self._add_codeblock(cmd, index)
|
|
431
403
|
self._openbracket(index)
|
|
432
404
|
|
|
@@ -437,37 +409,37 @@ class DFTemplate:
|
|
|
437
409
|
self._openbracket(index)
|
|
438
410
|
|
|
439
411
|
|
|
440
|
-
def repeat(self, name: str, *args, sub_action: str=None, index: int|None=None):
|
|
441
|
-
args =
|
|
412
|
+
def repeat(self, name: str, *args, tags: dict[str, str]={}, sub_action: str=None, index: int|None=None):
|
|
413
|
+
args = _convert_args(args)
|
|
442
414
|
data = {'id': 'block', 'block': 'repeat', 'action': name}
|
|
443
415
|
if sub_action is not None:
|
|
444
416
|
data['subAction'] = sub_action
|
|
445
|
-
cmd = CodeBlock(name, args, data=data)
|
|
417
|
+
cmd = CodeBlock(name, args, data=data, tags=tags)
|
|
446
418
|
self._add_codeblock(cmd, index)
|
|
447
419
|
self._openbracket(index, 'repeat')
|
|
448
420
|
|
|
449
421
|
|
|
450
422
|
def bracket(self, *args, index: int|None=None):
|
|
451
|
-
args =
|
|
423
|
+
args = _convert_args(args)
|
|
452
424
|
cmd = CodeBlock('bracket', data={'id': 'bracket', 'direct': 'close', 'type': self.bracket_stack.pop()})
|
|
453
425
|
self._add_codeblock(cmd, index)
|
|
454
426
|
|
|
455
427
|
|
|
456
|
-
def control(self, name: str, *args, index: int|None=None):
|
|
457
|
-
args =
|
|
458
|
-
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'control', 'action': name})
|
|
428
|
+
def control(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
429
|
+
args = _convert_args(args)
|
|
430
|
+
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'control', 'action': name}, tags=tags)
|
|
459
431
|
self._add_codeblock(cmd, index)
|
|
460
432
|
|
|
461
433
|
|
|
462
|
-
def select_object(self, name: str, *args, index: int|None=None):
|
|
463
|
-
args =
|
|
464
|
-
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'select_obj', 'action': name})
|
|
434
|
+
def select_object(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
435
|
+
args = _convert_args(args)
|
|
436
|
+
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'select_obj', 'action': name}, tags=tags)
|
|
465
437
|
self._add_codeblock(cmd, index)
|
|
466
438
|
|
|
467
439
|
|
|
468
|
-
def set_variable(self, name: str, *args, index: int|None=None):
|
|
469
|
-
args =
|
|
470
|
-
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'set_var', 'action': name})
|
|
440
|
+
def set_variable(self, name: str, *args, tags: dict[str, str]={}, index: int|None=None):
|
|
441
|
+
args = _convert_args(args)
|
|
442
|
+
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'set_var', 'action': name}, tags=tags)
|
|
471
443
|
self._add_codeblock(cmd, index)
|
|
472
444
|
|
|
473
445
|
|
|
@@ -481,6 +453,6 @@ class DFTemplate:
|
|
|
481
453
|
:param bool var_shorthand: If True, all variables will be written using variable shorthand.
|
|
482
454
|
"""
|
|
483
455
|
flags = GeneratorFlags(indent_size, literal_shorthand, var_shorthand)
|
|
484
|
-
with open(output_path, 'w') as f:
|
|
456
|
+
with open(output_path, 'w', encoding='utf-8') as f:
|
|
485
457
|
f.write(generate_script(self, flags))
|
|
486
458
|
|
dfpyre/scriptgen.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import re
|
|
3
3
|
from dfpyre.items import *
|
|
4
|
+
from dfpyre.actiondump import get_default_tags
|
|
4
5
|
|
|
5
6
|
SCRIPT_START = '''from dfpyre import *
|
|
6
7
|
t = DFTemplate()
|
|
@@ -28,7 +29,6 @@ TEMPLATE_METHOD_LOOKUP = {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
TARGET_CODEBLOCKS = {'player_action', 'entity_action', 'if_player', 'if_entity'}
|
|
31
|
-
SINGLE_NAME_CODEBLOCKS = {'func', 'process', 'call_func', 'start_process'}
|
|
32
32
|
VAR_SCOPES = {'unsaved': 'g', 'saved': 's', 'local': 'l', 'line': 'i'}
|
|
33
33
|
|
|
34
34
|
|
|
@@ -96,7 +96,7 @@ def argument_item_to_string(flags: GeneratorFlags, arg_item: object) -> str:
|
|
|
96
96
|
if arg_item.optional:
|
|
97
97
|
param_args.append('optional=True')
|
|
98
98
|
if arg_item.default_value is not None:
|
|
99
|
-
param_args.append(f'default_value={argument_item_to_string(arg_item.default_value)}')
|
|
99
|
+
param_args.append(f'default_value={argument_item_to_string(flags, arg_item.default_value)}')
|
|
100
100
|
if arg_item.description:
|
|
101
101
|
param_args.append(f'description="{arg_item.description}"')
|
|
102
102
|
if arg_item.note:
|
|
@@ -114,6 +114,7 @@ def add_script_line(flags: GeneratorFlags, script_lines: list[str], indent_level
|
|
|
114
114
|
script_lines.append(added_line)
|
|
115
115
|
|
|
116
116
|
|
|
117
|
+
# TODO: add tag values if not default
|
|
117
118
|
def generate_script(template, flags: GeneratorFlags) -> str:
|
|
118
119
|
indent_level = 0
|
|
119
120
|
script_lines = []
|
|
@@ -132,7 +133,7 @@ def generate_script(template, flags: GeneratorFlags) -> str:
|
|
|
132
133
|
|
|
133
134
|
method_name = TEMPLATE_METHOD_LOOKUP[codeblock.data['block']]
|
|
134
135
|
method_args = [f'"{codeblock.name}"']
|
|
135
|
-
if codeblock.name
|
|
136
|
+
if codeblock.name == 'dynamic':
|
|
136
137
|
method_args[0] = f'"{codeblock.data["data"]}"'
|
|
137
138
|
|
|
138
139
|
codeblock_args = [argument_item_to_string(flags, i) for i in codeblock.args]
|
|
@@ -140,7 +141,12 @@ def generate_script(template, flags: GeneratorFlags) -> str:
|
|
|
140
141
|
method_args.extend(codeblock_args)
|
|
141
142
|
if method_name in TARGET_CODEBLOCKS and codeblock.target.name != 'SELECTION':
|
|
142
143
|
method_args.append(f'target=Target.{codeblock.target.name}')
|
|
144
|
+
if codeblock.tags:
|
|
145
|
+
default_tags = get_default_tags(codeblock.data.get('block'), codeblock.name)
|
|
146
|
+
written_tags = {t: o for t, o in codeblock.tags.items() if default_tags[t] != o}
|
|
147
|
+
if written_tags:
|
|
148
|
+
method_args.append(f'tags={str(written_tags)}')
|
|
143
149
|
|
|
144
150
|
line = f't.{method_name}({", ".join(method_args)})'
|
|
145
151
|
add_script_line(flags, script_lines, indent_level, line)
|
|
146
|
-
return SCRIPT_START + '\n'.join(script_lines)
|
|
152
|
+
return SCRIPT_START + '\n'.join(script_lines)
|
dfpyre/util.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import gzip
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
COL_WARN = '\x1b[33m'
|
|
6
|
+
COL_RESET = '\x1b[0m'
|
|
7
|
+
COL_SUCCESS = '\x1b[32m'
|
|
8
|
+
COL_ERROR = '\x1b[31m'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PyreException(Exception):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def warn(message: str):
|
|
16
|
+
print(f'{COL_WARN}! WARNING ! {message}{COL_RESET}')
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def df_encode(json_string: str) -> str:
|
|
20
|
+
"""
|
|
21
|
+
Encodes a stringified json.
|
|
22
|
+
"""
|
|
23
|
+
encoded_string = gzip.compress(json_string.encode('utf-8'))
|
|
24
|
+
return base64.b64encode(encoded_string).decode('utf-8')
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def df_decode(encoded_string: str) -> str:
|
|
28
|
+
return gzip.decompress(base64.b64decode(encoded_string)).decode('utf-8')
|