dfpyre 0.4.5__py3-none-any.whl → 0.8.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 +396 -361
- dfpyre/pyre.py +595 -433
- dfpyre/scriptgen.py +193 -0
- dfpyre/style.py +22 -22
- dfpyre/util.py +39 -0
- {dfpyre-0.4.5.dist-info → dfpyre-0.8.1.dist-info}/LICENSE +21 -21
- dfpyre-0.8.1.dist-info/METADATA +514 -0
- dfpyre-0.8.1.dist-info/RECORD +12 -0
- dfpyre/data/data.json +0 -1
- dfpyre-0.4.5.dist-info/METADATA +0 -448
- dfpyre-0.4.5.dist-info/RECORD +0 -9
- {dfpyre-0.4.5.dist-info → dfpyre-0.8.1.dist-info}/WHEEL +0 -0
dfpyre/pyre.py
CHANGED
|
@@ -1,433 +1,595 @@
|
|
|
1
|
-
"""
|
|
2
|
-
A package for
|
|
3
|
-
|
|
4
|
-
By Amp
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
from
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
f'&
|
|
207
|
-
'',
|
|
208
|
-
'
|
|
209
|
-
'&
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
'hypercube:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
self.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
1
|
+
"""
|
|
2
|
+
A package for making code templates for the DiamondFire Minecraft server.
|
|
3
|
+
|
|
4
|
+
By Amp
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
from difflib import get_close_matches
|
|
9
|
+
import datetime
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from mcitemlib.itemlib import Item as NbtItem
|
|
12
|
+
from dfpyre.util import *
|
|
13
|
+
from dfpyre.items import *
|
|
14
|
+
from dfpyre.scriptgen import generate_script, GeneratorFlags
|
|
15
|
+
from dfpyre.actiondump import CODEBLOCK_DATA, get_default_tags
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
VARIABLE_TYPES = {'txt', 'comp', 'num', 'item', 'loc', 'var', 'snd', 'part', 'pot', 'g_val', 'vec', 'pn_el'}
|
|
19
|
+
TEMPLATE_STARTERS = {'event', 'entity_event', 'func', 'process'}
|
|
20
|
+
DYNAMIC_CODEBLOCKS = {'func', 'process', 'call_func', 'start_process'}
|
|
21
|
+
|
|
22
|
+
TARGETS = ['Selection', 'Default', 'Killer', 'Damager', 'Shooter', 'Victim', 'AllPlayers', 'Projectile', 'AllEntities', 'AllMobs', 'LastEntity']
|
|
23
|
+
TARGET_CODEBLOCKS = {'player_action', 'entity_action', 'if_player', 'if_entity'}
|
|
24
|
+
|
|
25
|
+
CODECLIENT_URL = 'ws://localhost:31375'
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Target(Enum):
|
|
29
|
+
SELECTION = 0
|
|
30
|
+
DEFAULT = 1
|
|
31
|
+
KILLER = 2
|
|
32
|
+
DAMAGER = 3
|
|
33
|
+
SHOOTER = 4
|
|
34
|
+
VICTIM = 5
|
|
35
|
+
ALL_PLAYERS = 6
|
|
36
|
+
PROJECTILE = 7
|
|
37
|
+
ALL_ENTITIES = 8
|
|
38
|
+
ALL_MOBS = 9
|
|
39
|
+
LAST_ENTITY = 10
|
|
40
|
+
|
|
41
|
+
def get_string_value(self):
|
|
42
|
+
return TARGETS[self.value]
|
|
43
|
+
|
|
44
|
+
DEFAULT_TARGET = Target.SELECTION
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _convert_args(args):
|
|
48
|
+
return tuple(map(convert_argument, args))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CodeBlock:
|
|
52
|
+
def __init__(self, codeblock_type: str, action_name: str, args: tuple=(), target: Target=DEFAULT_TARGET, data: dict={}, tags: dict[str, str]={}):
|
|
53
|
+
self.type = codeblock_type
|
|
54
|
+
self.action_name = action_name
|
|
55
|
+
self.args = args
|
|
56
|
+
self.target = target
|
|
57
|
+
self.data = data
|
|
58
|
+
self.tags = tags
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def new_action(cls, codeblock_type: str, action_name: str, args: tuple, tags: dict[str, str], target: Target=DEFAULT_TARGET) -> "CodeBlock":
|
|
63
|
+
args = _convert_args(args)
|
|
64
|
+
return cls(codeblock_type, action_name, args=args, data={'id': 'block', 'block': codeblock_type, 'action': action_name}, tags=tags, target=target)
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def new_data(cls, codeblock_type: str, data_value: str, args: tuple, tags: dict[str, str]) -> "CodeBlock":
|
|
68
|
+
args = _convert_args(args)
|
|
69
|
+
return cls(codeblock_type, 'dynamic', args=args, data={'id': 'block', 'block': codeblock_type, 'data': data_value}, tags=tags)
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def new_conditional(cls, codeblock_type: str, action_name: str, args: tuple, tags: dict[str, str], inverted: bool, target: Target=DEFAULT_TARGET) -> "CodeBlock":
|
|
73
|
+
args = _convert_args(args)
|
|
74
|
+
data = {'id': 'block', 'block': codeblock_type, 'action': action_name}
|
|
75
|
+
if inverted:
|
|
76
|
+
data['attribute'] = 'NOT'
|
|
77
|
+
return cls(codeblock_type, action_name, args=args, data=data, tags=tags, target=target)
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def new_repeat(cls, action_name: str, args: tuple, tags: dict[str, str], sub_action: str|None, inverted: bool) -> "CodeBlock":
|
|
81
|
+
args = _convert_args(args)
|
|
82
|
+
data = {'id': 'block', 'block': 'repeat', 'action': action_name}
|
|
83
|
+
if inverted:
|
|
84
|
+
data['attribute'] = 'NOT'
|
|
85
|
+
if sub_action is not None:
|
|
86
|
+
data['subAction'] = sub_action
|
|
87
|
+
return cls('repeat', action_name, args=args, data=data, tags=tags)
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def new_else(cls) -> "CodeBlock":
|
|
91
|
+
return cls('else', 'else', data={'id': 'block', 'block': 'else'})
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def new_bracket(cls, direction: Literal['open', 'close'], bracket_type: Literal['norm', 'repeat']) -> "CodeBlock":
|
|
95
|
+
return cls('bracket', 'bracket', data={'id': 'bracket', 'direct': direction, 'type': bracket_type})
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def __repr__(self) -> str:
|
|
99
|
+
if self.action_name == 'dynamic':
|
|
100
|
+
return f'CodeBlock({self.data["block"]}, {self.data["data"]})'
|
|
101
|
+
if self.action_name == 'else':
|
|
102
|
+
return 'CodeBlock(else)'
|
|
103
|
+
if 'block' in self.data:
|
|
104
|
+
return f'CodeBlock({self.data["block"]}, {self.action_name})'
|
|
105
|
+
return f'CodeBlock(bracket, {self.data["type"]}, {self.data["direct"]})'
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def build(self, include_tags: bool=True) -> dict:
|
|
109
|
+
"""
|
|
110
|
+
Builds a properly formatted block from a CodeBlock object.
|
|
111
|
+
"""
|
|
112
|
+
built_block = self.data.copy()
|
|
113
|
+
|
|
114
|
+
# add target if necessary ('Selection' is the default when 'target' is blank)
|
|
115
|
+
if self.type in TARGET_CODEBLOCKS and self.target != DEFAULT_TARGET:
|
|
116
|
+
built_block['target'] = self.target.get_string_value()
|
|
117
|
+
|
|
118
|
+
# add items into args
|
|
119
|
+
final_args = [arg.format(slot) for slot, arg in enumerate(self.args) if arg.type in VARIABLE_TYPES]
|
|
120
|
+
|
|
121
|
+
# check for unrecognized name, add tags
|
|
122
|
+
if self.type not in {'bracket', 'else'}:
|
|
123
|
+
if self.action_name not in CODEBLOCK_DATA[self.type]:
|
|
124
|
+
_warn_unrecognized_name(self.type, self.action_name)
|
|
125
|
+
elif include_tags:
|
|
126
|
+
tags = _get_codeblock_tags(self.type, self.action_name, self.tags)
|
|
127
|
+
if len(final_args) + len(tags) > 27:
|
|
128
|
+
final_args = final_args[:(27-len(tags))] # trim list if over 27 elements
|
|
129
|
+
final_args.extend(tags) # add tags to end
|
|
130
|
+
|
|
131
|
+
built_block['args'] = {'items': final_args}
|
|
132
|
+
return built_block
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _warn_unrecognized_name(codeblock_type: str, codeblock_name: str):
|
|
136
|
+
close = get_close_matches(codeblock_name, CODEBLOCK_DATA[codeblock_type].keys())
|
|
137
|
+
if close:
|
|
138
|
+
warn(f'Code block name "{codeblock_name}" not recognized. Did you mean "{close[0]}"?')
|
|
139
|
+
else:
|
|
140
|
+
warn(f'Code block name "{codeblock_name}" not recognized. Try spell checking or retyping without spaces.')
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _check_applied_tags(tags: list[dict], applied_tags: dict[str, str], codeblock_name: str) -> dict[str, str]:
|
|
144
|
+
if len(applied_tags) > 0 and len(tags) == 0:
|
|
145
|
+
warn(f'Action "{codeblock_name}" does not have any tags, but still received {len(applied_tags)}.')
|
|
146
|
+
return {}
|
|
147
|
+
|
|
148
|
+
valid_tags = {}
|
|
149
|
+
tags_formatted = {t['name']: t for t in tags}
|
|
150
|
+
for name, option in applied_tags.items():
|
|
151
|
+
if name not in tags_formatted:
|
|
152
|
+
tag_names_joined = '\n'.join(map(lambda s: ' - '+s, tags_formatted.keys()))
|
|
153
|
+
warn(f'Tag "{name}" does not exist for action "{codeblock_name}". Available tags:\n{tag_names_joined}')
|
|
154
|
+
elif option not in tags_formatted[name]['options']:
|
|
155
|
+
options_joined = '\n'.join(map(lambda s: ' - '+s, tags_formatted[name]['options']))
|
|
156
|
+
warn(f'Tag "{name}" does not have the option "{option}". Available tag options:\n{options_joined}')
|
|
157
|
+
else:
|
|
158
|
+
valid_tags[name] = option
|
|
159
|
+
return valid_tags
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _reformat_codeblock_tags(tags: list[dict], codeblock_type: str, codeblock_action: str, applied_tags: dict[str, str]):
|
|
163
|
+
"""
|
|
164
|
+
Turns tag objects into DiamondFire formatted tag items
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def format_tag(option: str, name: str):
|
|
168
|
+
return {
|
|
169
|
+
'item': {
|
|
170
|
+
'id': 'bl_tag',
|
|
171
|
+
'data': {'option': option, 'tag': name, 'action': codeblock_action, 'block': codeblock_type}
|
|
172
|
+
},
|
|
173
|
+
'slot': tag_item['slot']
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
valid_applied_tags = _check_applied_tags(tags, applied_tags, codeblock_action)
|
|
177
|
+
reformatted_tags = []
|
|
178
|
+
for tag_item in tags:
|
|
179
|
+
tag_name = tag_item['name']
|
|
180
|
+
tag_option = tag_item['default']
|
|
181
|
+
if tag_name in valid_applied_tags:
|
|
182
|
+
tag_option = valid_applied_tags[tag_name]
|
|
183
|
+
|
|
184
|
+
new_tag_item = format_tag(tag_option, tag_name)
|
|
185
|
+
reformatted_tags.append(new_tag_item)
|
|
186
|
+
return reformatted_tags
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _get_codeblock_tags(codeblock_type: str, codeblock_name: str, applied_tags: dict[str, str]):
|
|
190
|
+
"""
|
|
191
|
+
Get tags for the specified codeblock type and name
|
|
192
|
+
"""
|
|
193
|
+
action_data = CODEBLOCK_DATA[codeblock_type][codeblock_name]
|
|
194
|
+
if 'deprecatedNote' in action_data:
|
|
195
|
+
warn(f'Action "{codeblock_name}" is deprecated: {action_data["deprecatedNote"]}')
|
|
196
|
+
tags = action_data['tags']
|
|
197
|
+
return _reformat_codeblock_tags(tags, codeblock_type, codeblock_name, applied_tags)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _get_template_item(template_code: str, name: str, author: str) -> NbtItem:
|
|
201
|
+
now = datetime.datetime.now()
|
|
202
|
+
|
|
203
|
+
template_item = NbtItem('yellow_shulker_box')
|
|
204
|
+
template_item.set_name(f'&x&f&f&5&c&0&0>> &x&f&f&c&7&0&0{name}')
|
|
205
|
+
template_item.set_lore([
|
|
206
|
+
f'&8Author: {author}',
|
|
207
|
+
f'&8Date: {now.strftime("%Y-%m-%d")}',
|
|
208
|
+
'',
|
|
209
|
+
'&7This template was generated by &6pyre&7.',
|
|
210
|
+
'&7https://github.com/Amp63/pyre'
|
|
211
|
+
])
|
|
212
|
+
|
|
213
|
+
pbv_tag = {
|
|
214
|
+
'hypercube:codetemplatedata': f'{{"author":"{author}","name":"{name}","version": 1,"code":"{template_code}"}}',
|
|
215
|
+
'hypercube:pyre_creation_timestamp': now.timestamp()
|
|
216
|
+
}
|
|
217
|
+
template_item.set_custom_data('PublicBukkitValues', pbv_tag, raw=True)
|
|
218
|
+
|
|
219
|
+
return template_item
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class DFTemplate:
|
|
223
|
+
"""
|
|
224
|
+
Represents a DiamondFire code template.
|
|
225
|
+
"""
|
|
226
|
+
def __init__(self, codeblocks: list[CodeBlock], author: str='pyre'):
|
|
227
|
+
self.codeblocks = codeblocks
|
|
228
|
+
self.author = author
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def _get_template_name(self):
|
|
232
|
+
first_block_data = self.codeblocks[0].data
|
|
233
|
+
if 'data' in first_block_data:
|
|
234
|
+
name = first_block_data['data']
|
|
235
|
+
return name if name else 'Unnamed Template'
|
|
236
|
+
return first_block_data['block'] + '_' + first_block_data['action']
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def __repr__(self) -> str:
|
|
240
|
+
return f'DFTemplate(name: "{self._get_template_name()}", author: "{self.author}", codeblocks: {len(self.codeblocks)})'
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
@staticmethod
|
|
244
|
+
def from_code(template_code: str):
|
|
245
|
+
"""
|
|
246
|
+
Create a template object from an existing template code.
|
|
247
|
+
"""
|
|
248
|
+
template_dict = json.loads(df_decode(template_code))
|
|
249
|
+
codeblocks: list[CodeBlock] = []
|
|
250
|
+
for block_dict in template_dict['blocks']:
|
|
251
|
+
block_tags = get_default_tags(block_dict.get('block'), block_dict.get('action'))
|
|
252
|
+
if 'args' in block_dict:
|
|
253
|
+
block_args = []
|
|
254
|
+
for item_dict in block_dict['args']['items']:
|
|
255
|
+
if item_dict['item'].get('id') == 'bl_tag':
|
|
256
|
+
tag_data = item_dict['item']['data']
|
|
257
|
+
block_tags[tag_data['tag']] = tag_data['option']
|
|
258
|
+
parsed_item = item_from_dict(item_dict['item'])
|
|
259
|
+
if parsed_item is not None:
|
|
260
|
+
block_args.append(parsed_item)
|
|
261
|
+
block_target = Target(TARGETS.index(block_dict['target'])) if 'target' in block_dict else DEFAULT_TARGET
|
|
262
|
+
|
|
263
|
+
codeblock_type = block_dict.get('block')
|
|
264
|
+
|
|
265
|
+
if codeblock_type is None:
|
|
266
|
+
codeblock = CodeBlock.new_bracket(block_dict['direct'], block_dict['type'])
|
|
267
|
+
if codeblock_type == 'else':
|
|
268
|
+
codeblock = CodeBlock.new_else()
|
|
269
|
+
elif codeblock_type in DYNAMIC_CODEBLOCKS:
|
|
270
|
+
codeblock = CodeBlock.new_data(codeblock_type, block_dict['data'], block_args, block_tags)
|
|
271
|
+
elif 'action' in block_dict:
|
|
272
|
+
codeblock = CodeBlock.new_action(codeblock_type, block_dict['action'], block_args, block_tags, block_target)
|
|
273
|
+
codeblocks.append(codeblock)
|
|
274
|
+
|
|
275
|
+
return DFTemplate(codeblocks)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def insert(self, insert_codeblocks: CodeBlock|list[CodeBlock], index: int=-1) -> "DFTemplate":
|
|
279
|
+
"""
|
|
280
|
+
Insert `insert_codeblocks` into this template at `index`.
|
|
281
|
+
|
|
282
|
+
:param CodeBlock|list[CodeBlock] insert_codeblocks: The block(s) to insert
|
|
283
|
+
:param int index: The index to insert at.
|
|
284
|
+
:return: self
|
|
285
|
+
"""
|
|
286
|
+
if isinstance(insert_codeblocks, list):
|
|
287
|
+
insert_codeblocks = list(flatten(insert_codeblocks))
|
|
288
|
+
if index == -1:
|
|
289
|
+
self.codeblocks.extend(insert_codeblocks)
|
|
290
|
+
else:
|
|
291
|
+
self.codeblocks[index:index+len(insert_codeblocks)] = insert_codeblocks
|
|
292
|
+
elif isinstance(insert_codeblocks, CodeBlock):
|
|
293
|
+
self.codeblocks.insert(index, insert_codeblocks)
|
|
294
|
+
else:
|
|
295
|
+
raise PyreException('Expected CodeBlock or list[CodeBlock] to insert.')
|
|
296
|
+
return self
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def build(self, include_tags: bool=True) -> str:
|
|
300
|
+
"""
|
|
301
|
+
Build this template.
|
|
302
|
+
|
|
303
|
+
:param bool include_tags: If True, include item tags in code blocks. Otherwise omit them.
|
|
304
|
+
:return: String containing encoded template data.
|
|
305
|
+
"""
|
|
306
|
+
template_dict_blocks = [codeblock.build(include_tags) for codeblock in self.codeblocks]
|
|
307
|
+
template_dict = {'blocks': template_dict_blocks}
|
|
308
|
+
first_block = template_dict_blocks[0]
|
|
309
|
+
if first_block['block'] not in TEMPLATE_STARTERS:
|
|
310
|
+
warn('Template does not start with an event, function, or process.')
|
|
311
|
+
|
|
312
|
+
json_string = json.dumps(template_dict, separators=(',', ':'))
|
|
313
|
+
return df_encode(json_string)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def build_and_send(self, method: Literal['recode', 'codeclient'], include_tags: bool=True) -> int:
|
|
317
|
+
"""
|
|
318
|
+
Builds this template and sends it to DiamondFire automatically.
|
|
319
|
+
|
|
320
|
+
:param bool include_tags: If True, include item tags in code blocks. Otherwise omit them.
|
|
321
|
+
"""
|
|
322
|
+
template_code = self.build(include_tags)
|
|
323
|
+
template_item = _get_template_item(template_code, self._get_template_name(), self.author)
|
|
324
|
+
return template_item.send_to_minecraft(method, 'pyre')
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def generate_script(self, output_path: str, indent_size: int=4, literal_shorthand: bool=True, var_shorthand: bool=False):
|
|
328
|
+
"""
|
|
329
|
+
Generate an equivalent python script for this template.
|
|
330
|
+
|
|
331
|
+
:param str output_path: The file path to write the script to.
|
|
332
|
+
:param int indent_size: The multiple of spaces to add when indenting lines.
|
|
333
|
+
:param bool literal_shorthand: If True, `text` and `num` items will be written as strings and ints respectively.
|
|
334
|
+
:param bool var_shorthand: If True, all variables will be written using variable shorthand.
|
|
335
|
+
"""
|
|
336
|
+
flags = GeneratorFlags(indent_size, literal_shorthand, var_shorthand)
|
|
337
|
+
with open(output_path, 'w', encoding='utf-8') as f:
|
|
338
|
+
f.write(generate_script(self, flags))
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def _assemble_template(starting_block: CodeBlock, codeblocks: list[CodeBlock], author: str|None) -> DFTemplate:
|
|
342
|
+
"""
|
|
343
|
+
Create a DFTemplate object from a starting block and a list of codeblocks.
|
|
344
|
+
`codeblocks` can contain nested lists of CodeBlock objects, so it must be flattened.
|
|
345
|
+
"""
|
|
346
|
+
if author is None:
|
|
347
|
+
author = 'pyre'
|
|
348
|
+
template_codeblocks = [starting_block] + list(flatten(codeblocks)) # flatten codeblocks list and insert starting block
|
|
349
|
+
return DFTemplate(template_codeblocks, author)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def player_event(event_name: str, codeblocks: list[CodeBlock]=(), author: str|None=None) -> DFTemplate:
|
|
353
|
+
"""
|
|
354
|
+
Represents a Player Event codeblock.
|
|
355
|
+
|
|
356
|
+
:param str event_name: The name of the event. (Ex: "Join")
|
|
357
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks in this template.
|
|
358
|
+
:param str|None author: The author of this template.
|
|
359
|
+
"""
|
|
360
|
+
starting_block = CodeBlock.new_action('event', event_name, (), {})
|
|
361
|
+
return _assemble_template(starting_block, codeblocks, author)
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def entity_event(event_name: str, codeblocks: list[CodeBlock]=[], author: str|None=None) -> DFTemplate:
|
|
365
|
+
"""
|
|
366
|
+
Represents an Entity Event codeblock.
|
|
367
|
+
|
|
368
|
+
:param str event_name: The name of the event. (Ex: "EntityDmg")
|
|
369
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks in this template.
|
|
370
|
+
:param str|None author: The author of this template.
|
|
371
|
+
"""
|
|
372
|
+
starting_block = CodeBlock.new_action('entity_event', event_name, (), {})
|
|
373
|
+
return _assemble_template(starting_block, codeblocks, author)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def function(function_name: str, *args, tags: dict[str, str]={}, codeblocks: list[CodeBlock]=[], author: str|None=None) -> DFTemplate:
|
|
377
|
+
"""
|
|
378
|
+
Represents a Function codeblock.
|
|
379
|
+
|
|
380
|
+
:param str event_name: The name of the function.
|
|
381
|
+
:param tuple args: The argument items to include.
|
|
382
|
+
:param dict[str, str] tags: The tags to include.
|
|
383
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks in this template.
|
|
384
|
+
:param str|None author: The author of this template.
|
|
385
|
+
"""
|
|
386
|
+
starting_block = CodeBlock.new_data('func', function_name, args, tags)
|
|
387
|
+
return _assemble_template(starting_block, codeblocks, author)
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def process(process_name: str, *args, tags: dict[str, str]={}, codeblocks: list[CodeBlock]=[], author: str|None=None) -> DFTemplate:
|
|
391
|
+
"""
|
|
392
|
+
Represents a Process codeblock.
|
|
393
|
+
|
|
394
|
+
:param str event_name: The name of the process.
|
|
395
|
+
:param tuple args: The argument items to include.
|
|
396
|
+
:param dict[str, str] tags: The tags to include.
|
|
397
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks in this template.
|
|
398
|
+
:param str|None author: The author of this template.
|
|
399
|
+
"""
|
|
400
|
+
starting_block = CodeBlock.new_data('process', process_name, args, tags)
|
|
401
|
+
return _assemble_template(starting_block, codeblocks, author)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def call_function(function_name: str, *args) -> CodeBlock:
|
|
405
|
+
"""
|
|
406
|
+
Represents a Call Function codeblock.
|
|
407
|
+
|
|
408
|
+
:param str event_name: The name of the function.
|
|
409
|
+
:param tuple args: The argument items to include.
|
|
410
|
+
"""
|
|
411
|
+
return CodeBlock.new_data('call_func', function_name, args, {})
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def start_process(process_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
|
|
415
|
+
"""
|
|
416
|
+
Represents a Call Function codeblock.
|
|
417
|
+
|
|
418
|
+
:param str event_name: The name of the function.
|
|
419
|
+
:param tuple args: The argument items to include.
|
|
420
|
+
"""
|
|
421
|
+
return CodeBlock.new_data('start_process', process_name, args, tags)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def player_action(action_name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}) -> CodeBlock:
|
|
425
|
+
"""
|
|
426
|
+
Represents a Player Action codeblock.
|
|
427
|
+
|
|
428
|
+
:param str action_name: The name of the action.
|
|
429
|
+
:param tuple args: The argument items to include.
|
|
430
|
+
:param Target target: The target for the action.
|
|
431
|
+
:param dict[str, str] tags: The tags to include.
|
|
432
|
+
"""
|
|
433
|
+
return CodeBlock.new_action('player_action', action_name, args, tags, target=target)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
def entity_action(action_name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}) -> CodeBlock:
|
|
437
|
+
"""
|
|
438
|
+
Represents an Entity Action codeblock.
|
|
439
|
+
|
|
440
|
+
:param str action_name: The name of the action.
|
|
441
|
+
:param tuple args: The argument items to include.
|
|
442
|
+
:param Target target: The target for the action.
|
|
443
|
+
:param dict[str, str] tags: The tags to include.
|
|
444
|
+
"""
|
|
445
|
+
return CodeBlock.new_action('entity_action', action_name, args, tags, target=target)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def game_action(action_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
|
|
449
|
+
"""
|
|
450
|
+
Represents a Game Action codeblock.
|
|
451
|
+
|
|
452
|
+
:param str action_name: The name of the action.
|
|
453
|
+
:param tuple args: The argument items to include.
|
|
454
|
+
:param dict[str, str] tags: The tags to include.
|
|
455
|
+
"""
|
|
456
|
+
return CodeBlock.new_action('game_action', action_name, args, tags)
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def if_player(action_name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
|
|
460
|
+
"""
|
|
461
|
+
Represents an If Player codeblock.
|
|
462
|
+
|
|
463
|
+
:param str action_name: The name of the condition.
|
|
464
|
+
:param tuple args: The argument items to include.
|
|
465
|
+
:param Target target: The target for the condition.
|
|
466
|
+
:param dict[str, str] tags: The tags to include.
|
|
467
|
+
:param bool inverted: Whether the condition should be inverted.
|
|
468
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks inside the brackets.
|
|
469
|
+
"""
|
|
470
|
+
return [
|
|
471
|
+
CodeBlock.new_conditional('if_player', action_name, args, tags, inverted, target),
|
|
472
|
+
CodeBlock.new_bracket('open', 'norm')
|
|
473
|
+
] + list(codeblocks) + [
|
|
474
|
+
CodeBlock.new_bracket('close', 'norm')
|
|
475
|
+
]
|
|
476
|
+
|
|
477
|
+
def if_entity(action_name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
|
|
478
|
+
"""
|
|
479
|
+
Represents an If Entity codeblock.
|
|
480
|
+
|
|
481
|
+
:param str action_name: The name of the condition.
|
|
482
|
+
:param tuple args: The argument items to include.
|
|
483
|
+
:param Target target: The target for the condition.
|
|
484
|
+
:param dict[str, str] tags: The tags to include.
|
|
485
|
+
:param bool inverted: Whether the condition should be inverted.
|
|
486
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks inside the brackets.
|
|
487
|
+
"""
|
|
488
|
+
return [
|
|
489
|
+
CodeBlock.new_conditional('if_entity', action_name, args, tags, inverted, target),
|
|
490
|
+
CodeBlock.new_bracket('open', 'norm')
|
|
491
|
+
] + list(codeblocks) + [
|
|
492
|
+
CodeBlock.new_bracket('close', 'norm')
|
|
493
|
+
]
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
def if_game(action_name: str, *args, tags: dict[str, str]={}, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
|
|
497
|
+
"""
|
|
498
|
+
Represents an If Game codeblock.
|
|
499
|
+
|
|
500
|
+
:param str action_name: The name of the condition.
|
|
501
|
+
:param tuple args: The argument items to include.
|
|
502
|
+
:param dict[str, str] tags: The tags to include.
|
|
503
|
+
:param bool inverted: Whether the condition should be inverted.
|
|
504
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks inside the brackets.
|
|
505
|
+
"""
|
|
506
|
+
return [
|
|
507
|
+
CodeBlock.new_conditional('if_game', action_name, args, tags, inverted),
|
|
508
|
+
CodeBlock.new_bracket('open', 'norm')
|
|
509
|
+
] + list(codeblocks) + [
|
|
510
|
+
CodeBlock.new_bracket('close', 'norm')
|
|
511
|
+
]
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def if_variable(action_name: str, *args, tags: dict[str, str]={}, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
|
|
515
|
+
"""
|
|
516
|
+
Represents an If Variable codeblock.
|
|
517
|
+
|
|
518
|
+
:param str action_name: The name of the condition.
|
|
519
|
+
:param tuple args: The argument items to include.
|
|
520
|
+
:param dict[str, str] tags: The tags to include.
|
|
521
|
+
:param bool inverted: Whether the condition should be inverted.
|
|
522
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks inside the brackets.
|
|
523
|
+
"""
|
|
524
|
+
return [
|
|
525
|
+
CodeBlock.new_conditional('if_var', action_name, args, tags, inverted),
|
|
526
|
+
CodeBlock.new_bracket('open', 'norm')
|
|
527
|
+
] + list(codeblocks) + [
|
|
528
|
+
CodeBlock.new_bracket('close', 'norm')
|
|
529
|
+
]
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
def else_(codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
|
|
533
|
+
"""
|
|
534
|
+
Represents an Else codeblock.
|
|
535
|
+
|
|
536
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks inside the brackets.
|
|
537
|
+
"""
|
|
538
|
+
return [
|
|
539
|
+
CodeBlock.new_else(),
|
|
540
|
+
CodeBlock.new_bracket('open', 'norm')
|
|
541
|
+
] + list(codeblocks) + [
|
|
542
|
+
CodeBlock.new_bracket('close', 'norm')
|
|
543
|
+
]
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def repeat(action_name: str, *args, tags: dict[str, str]={}, sub_action: str|None=None, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> CodeBlock:
|
|
547
|
+
"""
|
|
548
|
+
Represents a Repeat codeblock.
|
|
549
|
+
|
|
550
|
+
:param str action_name: The name of the action.
|
|
551
|
+
:param tuple args: The argument items to include.
|
|
552
|
+
:param dict[str, str] tags: The tags to include.
|
|
553
|
+
:param str|None sub_action: The sub-action for the repeat action (Only relevant for `While`)
|
|
554
|
+
:param bool inverted: Whether the sub-action condition should be inverted.
|
|
555
|
+
:param list[CodeBlock] codeblocks: The list of codeblocks inside the brackets.
|
|
556
|
+
"""
|
|
557
|
+
return [
|
|
558
|
+
CodeBlock.new_repeat(action_name, args, tags, sub_action, inverted),
|
|
559
|
+
CodeBlock.new_bracket('open', 'repeat')
|
|
560
|
+
] + list(codeblocks) + [
|
|
561
|
+
CodeBlock.new_bracket('close', 'repeat')
|
|
562
|
+
]
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
def control(action_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
|
|
566
|
+
"""
|
|
567
|
+
Represents a Control codeblock.
|
|
568
|
+
|
|
569
|
+
:param str action_name: The name of the action.
|
|
570
|
+
:param tuple args: The argument items to include.
|
|
571
|
+
:param dict[str, str] tags: The tags to include.
|
|
572
|
+
"""
|
|
573
|
+
return CodeBlock.new_action('control', action_name, args, tags)
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
def select_object(action_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
|
|
577
|
+
"""
|
|
578
|
+
Represents a Select Object codeblock.
|
|
579
|
+
|
|
580
|
+
:param str action_name: The name of the action.
|
|
581
|
+
:param tuple args: The argument items to include.
|
|
582
|
+
:param dict[str, str] tags: The tags to include.
|
|
583
|
+
"""
|
|
584
|
+
return CodeBlock.new_action('select_obj', action_name, args, tags)
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def set_variable(action_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
|
|
588
|
+
"""
|
|
589
|
+
Represents a Set Variable codeblock.
|
|
590
|
+
|
|
591
|
+
:param str action_name: The name of the action.
|
|
592
|
+
:param tuple args: The argument items to include.
|
|
593
|
+
:param dict[str, str] tags: The tags to include.
|
|
594
|
+
"""
|
|
595
|
+
return CodeBlock.new_action('set_var', action_name, args, tags)
|