dfpyre 0.4.6__py3-none-any.whl → 0.6.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/items.py +130 -169
- dfpyre/pyre.py +220 -220
- dfpyre/scriptgen.py +144 -0
- dfpyre/style.py +14 -14
- {dfpyre-0.4.6.dist-info → dfpyre-0.6.0.dist-info}/LICENSE +1 -1
- {dfpyre-0.4.6.dist-info → dfpyre-0.6.0.dist-info}/METADATA +106 -80
- dfpyre-0.6.0.dist-info/RECORD +10 -0
- dfpyre-0.4.6.dist-info/RECORD +0 -9
- {dfpyre-0.4.6.dist-info → dfpyre-0.6.0.dist-info}/WHEEL +0 -0
dfpyre/pyre.py
CHANGED
|
@@ -2,22 +2,20 @@
|
|
|
2
2
|
A package for externally creating code templates for the DiamondFire Minecraft server.
|
|
3
3
|
|
|
4
4
|
By Amp
|
|
5
|
-
2/24/2024
|
|
6
5
|
"""
|
|
7
6
|
|
|
8
7
|
import base64
|
|
9
8
|
import gzip
|
|
10
|
-
import socket
|
|
11
|
-
import websocket
|
|
12
|
-
import time
|
|
13
9
|
import json
|
|
14
10
|
import os
|
|
15
11
|
from difflib import get_close_matches
|
|
16
12
|
import datetime
|
|
17
13
|
from typing import Tuple, List, Dict
|
|
18
14
|
from enum import Enum
|
|
15
|
+
import socket
|
|
19
16
|
from mcitemlib.itemlib import Item as NbtItem
|
|
20
17
|
from dfpyre.items import *
|
|
18
|
+
from dfpyre.scriptgen import generate_script, GeneratorFlags
|
|
21
19
|
|
|
22
20
|
COL_WARN = '\x1b[33m'
|
|
23
21
|
COL_RESET = '\x1b[0m'
|
|
@@ -28,6 +26,7 @@ CODEBLOCK_DATA_PATH = os.path.join(os.path.dirname(__file__), 'data/data.json')
|
|
|
28
26
|
|
|
29
27
|
VARIABLE_TYPES = {'txt', 'comp', 'num', 'item', 'loc', 'var', 'snd', 'part', 'pot', 'g_val', 'vec', 'pn_el'}
|
|
30
28
|
TEMPLATE_STARTERS = {'event', 'entity_event', 'func', 'process'}
|
|
29
|
+
SINGLE_NAME_CODEBLOCKS = {'func', 'process', 'call_func', 'start_process', 'else'}
|
|
31
30
|
|
|
32
31
|
TARGETS = ['Selection', 'Default', 'Killer', 'Damager', 'Shooter', 'Victim', 'AllPlayers', 'Projectile', 'AllEntities', 'AllMobs', 'LastEntity']
|
|
33
32
|
TARGET_CODEBLOCKS = {'player_action', 'entity_action', 'if_player', 'if_entity'}
|
|
@@ -51,7 +50,7 @@ class Target(Enum):
|
|
|
51
50
|
ALL_MOBS = 9
|
|
52
51
|
LAST_ENTITY = 10
|
|
53
52
|
|
|
54
|
-
def
|
|
53
|
+
def get_string_value(self):
|
|
55
54
|
return TARGETS[self.value]
|
|
56
55
|
|
|
57
56
|
DEFAULT_TARGET = Target.SELECTION
|
|
@@ -63,41 +62,50 @@ class CodeBlock:
|
|
|
63
62
|
self.args = args
|
|
64
63
|
self.target = target
|
|
65
64
|
self.data = data
|
|
65
|
+
|
|
66
|
+
def __repr__(self) -> str:
|
|
67
|
+
if self.name in SINGLE_NAME_CODEBLOCKS:
|
|
68
|
+
if self.name == 'else':
|
|
69
|
+
return 'CodeBlock(else)'
|
|
70
|
+
return f'CodeBlock({self.name}, {self.data["data"]})'
|
|
71
|
+
elif 'block' in self.data:
|
|
72
|
+
return f'CodeBlock({self.data["block"]}, {self.name})'
|
|
73
|
+
return f'CodeBlock(bracket, {self.data["type"]}, {self.data["direct"]})'
|
|
66
74
|
|
|
67
75
|
|
|
68
76
|
def _warn(message):
|
|
69
77
|
print(f'{COL_WARN}! WARNING ! {message}{COL_RESET}')
|
|
70
78
|
|
|
71
79
|
|
|
72
|
-
def
|
|
73
|
-
close = get_close_matches(
|
|
80
|
+
def _warn_unrecognized_name(codeblock_type: str, codeblock_name: str):
|
|
81
|
+
close = get_close_matches(codeblock_name, TAGDATA[codeblock_type].keys())
|
|
74
82
|
if close:
|
|
75
|
-
_warn(f'Code block name "{
|
|
83
|
+
_warn(f'Code block name "{codeblock_name}" not recognized. Did you mean "{close[0]}"?')
|
|
76
84
|
else:
|
|
77
|
-
_warn(f'Code block name "{
|
|
85
|
+
_warn(f'Code block name "{codeblock_name}" not recognized. Try spell checking or retyping without spaces.')
|
|
78
86
|
|
|
79
87
|
|
|
80
|
-
def
|
|
81
|
-
|
|
88
|
+
def _load_codeblock_data() -> Tuple:
|
|
89
|
+
tag_data = {}
|
|
82
90
|
if os.path.exists(CODEBLOCK_DATA_PATH):
|
|
83
91
|
with open(CODEBLOCK_DATA_PATH, 'r') as f:
|
|
84
|
-
|
|
92
|
+
tag_data = json.load(f)
|
|
85
93
|
else:
|
|
86
94
|
_warn('data.json not found -- Item tags and error checking will not work.')
|
|
87
95
|
return ({}, set(), set())
|
|
88
96
|
|
|
89
|
-
del
|
|
97
|
+
del tag_data['meta']
|
|
90
98
|
|
|
91
|
-
|
|
99
|
+
all_names = [x for l in [d.keys() for d in tag_data.values()] for x in l] # flatten list
|
|
92
100
|
return (
|
|
93
|
-
|
|
94
|
-
set(
|
|
95
|
-
set(
|
|
101
|
+
tag_data,
|
|
102
|
+
set(tag_data['extras'].keys()),
|
|
103
|
+
set(all_names)
|
|
96
104
|
)
|
|
97
105
|
|
|
98
|
-
TAGDATA, TAGDATA_EXTRAS_KEYS, ALL_CODEBLOCK_NAMES =
|
|
106
|
+
TAGDATA, TAGDATA_EXTRAS_KEYS, ALL_CODEBLOCK_NAMES = _load_codeblock_data()
|
|
99
107
|
|
|
100
|
-
def
|
|
108
|
+
def _add_inverted(data, inverted):
|
|
101
109
|
"""
|
|
102
110
|
If inverted is true, add 'inverted': 'NOT' to data.
|
|
103
111
|
"""
|
|
@@ -105,99 +113,103 @@ def _addInverted(data, inverted):
|
|
|
105
113
|
data['inverted'] = 'NOT'
|
|
106
114
|
|
|
107
115
|
|
|
108
|
-
def
|
|
109
|
-
|
|
116
|
+
def _convert_data_types(args):
|
|
117
|
+
converted_args = []
|
|
110
118
|
for value in args:
|
|
111
119
|
if type(value) in {int, float}:
|
|
112
|
-
|
|
120
|
+
converted_args.append(num(value))
|
|
113
121
|
elif type(value) is str:
|
|
114
|
-
if value[0] == VAR_SHORTHAND_CHAR and value[1] in VAR_SCOPES:
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
if len(value) > 2 and value[0] == VAR_SHORTHAND_CHAR and value[1] in VAR_SCOPES:
|
|
123
|
+
var_object = var(value[2:], VAR_SCOPES[value[1]])
|
|
124
|
+
converted_args.append(var_object)
|
|
117
125
|
else:
|
|
118
|
-
|
|
126
|
+
converted_args.append(text(value))
|
|
119
127
|
else:
|
|
120
|
-
|
|
121
|
-
return tuple(
|
|
128
|
+
converted_args.append(value)
|
|
129
|
+
return tuple(converted_args)
|
|
122
130
|
|
|
123
131
|
|
|
124
|
-
def
|
|
132
|
+
def _reformat_codeblock_tags(tags, codeblock_type: str, codeblock_name: str):
|
|
125
133
|
"""
|
|
126
134
|
Turns data.json tag items into DiamondFire formatted tag items
|
|
127
135
|
"""
|
|
128
|
-
|
|
129
|
-
for
|
|
130
|
-
|
|
131
|
-
|
|
136
|
+
reformatted_tags = []
|
|
137
|
+
for tag_item in tags:
|
|
138
|
+
action_value = codeblock_name if 'action' not in tag_item else tag_item['action']
|
|
139
|
+
new_tag_item = {
|
|
132
140
|
'item': {
|
|
133
141
|
'id': 'bl_tag',
|
|
134
142
|
'data': {
|
|
135
|
-
'option':
|
|
136
|
-
'tag':
|
|
137
|
-
'action':
|
|
138
|
-
'block':
|
|
143
|
+
'option': tag_item['option'],
|
|
144
|
+
'tag': tag_item['tag'],
|
|
145
|
+
'action': action_value,
|
|
146
|
+
'block': codeblock_type
|
|
139
147
|
}
|
|
140
148
|
},
|
|
141
|
-
'slot':
|
|
149
|
+
'slot': tag_item['slot']
|
|
142
150
|
}
|
|
143
|
-
|
|
144
|
-
return
|
|
151
|
+
reformatted_tags.append(new_tag_item)
|
|
152
|
+
return reformatted_tags
|
|
145
153
|
|
|
146
154
|
|
|
147
|
-
def
|
|
155
|
+
def _get_codeblock_tags(codeblock_type: str, codeblock_name: str):
|
|
148
156
|
"""
|
|
149
157
|
Get tags for the specified codeblock type and name
|
|
150
158
|
"""
|
|
151
159
|
tags = None
|
|
152
|
-
if
|
|
153
|
-
tags = TAGDATA['extras'][
|
|
160
|
+
if codeblock_type in TAGDATA_EXTRAS_KEYS:
|
|
161
|
+
tags = TAGDATA['extras'][codeblock_type]
|
|
154
162
|
else:
|
|
155
|
-
tags = TAGDATA[
|
|
156
|
-
return
|
|
163
|
+
tags = TAGDATA[codeblock_type].get(codeblock_name)
|
|
164
|
+
return _reformat_codeblock_tags(tags, codeblock_type, codeblock_name)
|
|
157
165
|
|
|
158
166
|
|
|
159
|
-
def
|
|
167
|
+
def _build_block(codeblock: CodeBlock, include_tags: bool):
|
|
160
168
|
"""
|
|
161
169
|
Builds a properly formatted block from a CodeBlock object.
|
|
162
170
|
"""
|
|
163
|
-
|
|
164
|
-
|
|
171
|
+
built_block = codeblock.data.copy()
|
|
172
|
+
codeblock_type = codeblock.data.get('block')
|
|
165
173
|
|
|
166
174
|
# add target if necessary ('Selection' is the default when 'target' is blank)
|
|
167
|
-
if
|
|
168
|
-
|
|
175
|
+
if codeblock_type in TARGET_CODEBLOCKS and codeblock.target != DEFAULT_TARGET:
|
|
176
|
+
built_block['target'] = codeblock.target.get_string_value()
|
|
169
177
|
|
|
170
178
|
# add items into args
|
|
171
|
-
|
|
179
|
+
final_args = [arg.format(slot) for slot, arg in enumerate(codeblock.args) if arg.type in VARIABLE_TYPES]
|
|
172
180
|
|
|
173
181
|
# check for unrecognized name, add tags
|
|
174
|
-
if
|
|
175
|
-
if
|
|
176
|
-
|
|
177
|
-
elif
|
|
178
|
-
tags =
|
|
179
|
-
if len(
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
182
190
|
|
|
183
|
-
|
|
184
|
-
return
|
|
191
|
+
built_block['args'] = {'items': final_args}
|
|
192
|
+
return built_block
|
|
185
193
|
|
|
186
194
|
|
|
187
|
-
def
|
|
195
|
+
def _df_encode(json_string: str) -> str:
|
|
188
196
|
"""
|
|
189
197
|
Encodes a stringified json.
|
|
190
198
|
"""
|
|
191
|
-
|
|
192
|
-
return base64.b64encode(
|
|
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')
|
|
193
205
|
|
|
194
206
|
|
|
195
|
-
def
|
|
207
|
+
def _get_template_item(template_code: str, name: str, author: str) -> NbtItem:
|
|
196
208
|
now = datetime.datetime.now()
|
|
197
209
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
210
|
+
template_item = NbtItem('yellow_shulker_box')
|
|
211
|
+
template_item.set_name(f'&x&f&f&5&c&0&0>> &x&f&f&c&7&0&0{name}')
|
|
212
|
+
template_item.set_lore([
|
|
201
213
|
f'&8Author: {author}',
|
|
202
214
|
f'&8Date: {now.strftime("%Y-%m-%d")}',
|
|
203
215
|
'',
|
|
@@ -205,138 +217,110 @@ def getTemplateItem(templateCode: str, name: str, author: str) -> NbtItem:
|
|
|
205
217
|
'&7https://github.com/Amp63/pyre'
|
|
206
218
|
])
|
|
207
219
|
|
|
208
|
-
|
|
209
|
-
'hypercube:codetemplatedata': f'{{"author":"{author}","name":"{name}","version": 1,"code":"{
|
|
220
|
+
pbv_tag = {
|
|
221
|
+
'hypercube:codetemplatedata': f'{{"author":"{author}","name":"{name}","version": 1,"code":"{template_code}"}}',
|
|
210
222
|
'hypercube:pyre_creation_timestamp': now.timestamp()
|
|
211
223
|
}
|
|
212
|
-
|
|
224
|
+
template_item.set_tag('PublicBukkitValues', pbv_tag, raw=True)
|
|
213
225
|
|
|
214
|
-
return
|
|
226
|
+
return template_item
|
|
215
227
|
|
|
216
228
|
|
|
217
|
-
|
|
229
|
+
# TODO:
|
|
230
|
+
# - add inserting codeblocks at any index
|
|
231
|
+
class DFTemplate:
|
|
218
232
|
"""
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
:param str templateCode: The code for the template as a base64 string.
|
|
222
|
-
:param str name: The name of the template.
|
|
223
|
-
:param str author: The author of the template.
|
|
224
|
-
|
|
225
|
-
:return: status code
|
|
226
|
-
- `0` = Success
|
|
227
|
-
- `1` = Connection refused
|
|
228
|
-
- `2` = Other socket error
|
|
233
|
+
Represents a DiamondFire code template.
|
|
229
234
|
"""
|
|
235
|
+
def __init__(self, name: str=None, author: str='pyre'):
|
|
236
|
+
self.codeblocks: List[CodeBlock] = []
|
|
237
|
+
self.bracket_stack: list[str] = []
|
|
238
|
+
self.name = name
|
|
239
|
+
self.author = author
|
|
230
240
|
|
|
231
|
-
templateItem = getTemplateItem(templateCode, name, author)
|
|
232
|
-
data = {'type': 'nbt', 'source': f'pyre Template - {name}', 'data': templateItem.get_nbt()}
|
|
233
|
-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
234
|
-
try:
|
|
235
|
-
s.connect(('127.0.0.1', 31372))
|
|
236
|
-
except ConnectionRefusedError:
|
|
237
|
-
print(f"""{COL_ERROR}Could not connect to recode item API. Possible problems:
|
|
238
|
-
- Minecraft is not open
|
|
239
|
-
- Recode is not installed (get it here: https://modrinth.com/mod/recode or join the discord here: https://discord.gg/GWxWtcwA2C){COL_RESET}""")
|
|
240
|
-
s.close()
|
|
241
|
-
return 1
|
|
242
|
-
|
|
243
|
-
s.send((str(data) + '\n').encode('utf-8'))
|
|
244
|
-
received = json.loads(s.recv(1024).decode())
|
|
245
|
-
status = received['status']
|
|
246
|
-
s.close()
|
|
247
|
-
time.sleep(0.5)
|
|
248
|
-
|
|
249
|
-
if status == 'success':
|
|
250
|
-
print(f'{COL_SUCCESS}Template sent to client successfully.{COL_RESET}')
|
|
251
|
-
return 0
|
|
252
|
-
error = received['error']
|
|
253
|
-
print(f'{COL_ERROR}Error sending template: {error}{COL_RESET}')
|
|
254
|
-
return 2
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
def sendCodeClient(templateCode: str, name: str='Unnamed Template', author: str='pyre') -> int:
|
|
258
|
-
try:
|
|
259
|
-
ws = websocket.WebSocket()
|
|
260
|
-
ws.connect(CODECLIENT_URL)
|
|
261
|
-
print(f'{COL_SUCCESS}Connected. {COL_WARN}Please run /auth in game.{COL_RESET}')
|
|
262
|
-
|
|
263
|
-
ws.recv() # auth response
|
|
264
241
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
ws.send(command)
|
|
268
|
-
ws.close()
|
|
242
|
+
def __repr__(self) -> str:
|
|
243
|
+
return f'DFTemplate(name: {self.name}, author: {self.author}, codeblocks: {len(self.codeblocks)})'
|
|
269
244
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
245
|
+
|
|
246
|
+
@staticmethod
|
|
247
|
+
def from_code(template_code: str):
|
|
248
|
+
"""
|
|
249
|
+
Create a template object from an existing template code.
|
|
250
|
+
"""
|
|
251
|
+
template_dict = json.loads(_df_decode(template_code))
|
|
252
|
+
template = DFTemplate()
|
|
253
|
+
for block_dict in template_dict['blocks']:
|
|
254
|
+
if 'args' in block_dict:
|
|
255
|
+
args = []
|
|
256
|
+
for item_dict in block_dict['args']['items']:
|
|
257
|
+
parsed_item = item_from_dict(item_dict['item'])
|
|
258
|
+
if parsed_item is not None:
|
|
259
|
+
args.append(parsed_item)
|
|
260
|
+
target = Target(TARGETS.index(block_dict['target'])) if 'target' in block_dict else DEFAULT_TARGET
|
|
261
|
+
|
|
262
|
+
codeblock_name = 'bracket'
|
|
263
|
+
if 'block' in block_dict and block_dict['block'] in SINGLE_NAME_CODEBLOCKS:
|
|
264
|
+
codeblock_name = block_dict['block']
|
|
265
|
+
elif 'action' in block_dict:
|
|
266
|
+
codeblock_name = block_dict['action']
|
|
267
|
+
codeblock = CodeBlock(codeblock_name, args, target, block_dict)
|
|
268
|
+
template.codeblocks.append(codeblock)
|
|
280
269
|
|
|
281
|
-
|
|
282
|
-
return 2
|
|
270
|
+
return template
|
|
283
271
|
|
|
284
272
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
self.author = author
|
|
273
|
+
@staticmethod
|
|
274
|
+
def receive_from_recode():
|
|
275
|
+
print('Waiting for item to be sent...')
|
|
276
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
277
|
+
s.connect(('localhost', 31372))
|
|
278
|
+
received = s.recv(8192)
|
|
279
|
+
print(received)
|
|
280
|
+
s.close()
|
|
294
281
|
|
|
295
282
|
|
|
296
|
-
def
|
|
283
|
+
def _set_template_name(self, first_block):
|
|
297
284
|
if self.name is not None:
|
|
298
285
|
return
|
|
299
|
-
if 'data' in
|
|
300
|
-
self.name =
|
|
286
|
+
if 'data' in first_block:
|
|
287
|
+
self.name = first_block['data']
|
|
301
288
|
if not self.name:
|
|
302
289
|
self.name = 'Unnamed Template'
|
|
303
290
|
else:
|
|
304
|
-
self.name =
|
|
291
|
+
self.name = first_block['block'] + '_' + first_block['action']
|
|
305
292
|
|
|
306
293
|
|
|
307
|
-
def build(self,
|
|
294
|
+
def build(self, include_tags: bool=True) -> str:
|
|
308
295
|
"""
|
|
309
296
|
Build this template.
|
|
310
297
|
|
|
311
|
-
:param bool
|
|
298
|
+
:param bool include_tags: If True, include item tags in code blocks. Otherwise omit them.
|
|
312
299
|
:return: String containing encoded template data.
|
|
313
300
|
"""
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if
|
|
301
|
+
template_dict_blocks = [_build_block(codeblock, include_tags) for codeblock in self.codeblocks]
|
|
302
|
+
template_dict = {'blocks': template_dict_blocks}
|
|
303
|
+
first_block = template_dict_blocks[0]
|
|
304
|
+
if first_block['block'] not in TEMPLATE_STARTERS:
|
|
318
305
|
_warn('Template does not start with an event, function, or process.')
|
|
319
306
|
|
|
320
|
-
self.
|
|
307
|
+
self._set_template_name(first_block)
|
|
321
308
|
|
|
322
309
|
print(f'{COL_SUCCESS}Template built successfully.{COL_RESET}')
|
|
323
310
|
|
|
324
|
-
|
|
325
|
-
return
|
|
311
|
+
json_string = json.dumps(template_dict, separators=(',', ':'))
|
|
312
|
+
return _df_encode(json_string)
|
|
326
313
|
|
|
327
314
|
|
|
328
|
-
def
|
|
315
|
+
def build_and_send(self, method: Literal['recode', 'codeclient'], includeTags: bool=True) -> int:
|
|
329
316
|
"""
|
|
330
317
|
Builds this template and sends it to DiamondFire automatically.
|
|
331
318
|
|
|
332
319
|
:param bool includeTags: If True, include item tags in code blocks. Otherwise omit them.
|
|
333
320
|
"""
|
|
334
321
|
templateCode = self.build(includeTags)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if sendMethod == 'codeclient':
|
|
338
|
-
return sendCodeClient(templateCode, name=self.name, author=self.author)
|
|
339
|
-
return -1
|
|
322
|
+
templateItem = _get_template_item(templateCode, self.name, self.author)
|
|
323
|
+
return templateItem.send_to_minecraft(method, 'pyre')
|
|
340
324
|
|
|
341
325
|
|
|
342
326
|
def clear(self):
|
|
@@ -347,133 +331,149 @@ class DFTemplate:
|
|
|
347
331
|
|
|
348
332
|
|
|
349
333
|
def _openbracket(self, btype: Literal['norm', 'repeat']='norm'):
|
|
350
|
-
bracket = CodeBlock('
|
|
351
|
-
self.
|
|
352
|
-
self.
|
|
334
|
+
bracket = CodeBlock('bracket', data={'id': 'bracket', 'direct': 'open', 'type': btype})
|
|
335
|
+
self.codeblocks.append(bracket)
|
|
336
|
+
self.bracket_stack.append(btype)
|
|
353
337
|
|
|
354
338
|
|
|
355
339
|
# command methods
|
|
356
|
-
def
|
|
340
|
+
def player_event(self, name: str):
|
|
357
341
|
cmd = CodeBlock(name, data={'id': 'block', 'block': 'event', 'action': name})
|
|
358
|
-
self.
|
|
342
|
+
self.codeblocks.append(cmd)
|
|
359
343
|
|
|
360
344
|
|
|
361
|
-
def
|
|
345
|
+
def entity_event(self, name: str):
|
|
362
346
|
cmd = CodeBlock(name, data={'id': 'block', 'block': 'entity_event', 'action': name})
|
|
363
|
-
self.
|
|
347
|
+
self.codeblocks.append(cmd)
|
|
364
348
|
|
|
365
349
|
|
|
366
350
|
def function(self, name: str, *args):
|
|
367
|
-
args =
|
|
368
|
-
cmd = CodeBlock('
|
|
369
|
-
self.
|
|
351
|
+
args = _convert_data_types(args)
|
|
352
|
+
cmd = CodeBlock('func', args, data={'id': 'block', 'block': 'func', 'data': name})
|
|
353
|
+
self.codeblocks.append(cmd)
|
|
370
354
|
|
|
371
355
|
|
|
372
|
-
def process(self, name: str):
|
|
373
|
-
|
|
374
|
-
|
|
356
|
+
def process(self, name: str, *args):
|
|
357
|
+
args = _convert_data_types(args)
|
|
358
|
+
cmd = CodeBlock('process', args, data={'id': 'block', 'block': 'process', 'data': name})
|
|
359
|
+
self.codeblocks.append(cmd)
|
|
375
360
|
|
|
376
361
|
|
|
377
|
-
def
|
|
378
|
-
args =
|
|
362
|
+
def call_function(self, name: str, *args):
|
|
363
|
+
args = _convert_data_types(args)
|
|
379
364
|
cmd = CodeBlock('call_func', args, data={'id': 'block', 'block': 'call_func', 'data': name})
|
|
380
|
-
self.
|
|
365
|
+
self.codeblocks.append(cmd)
|
|
381
366
|
|
|
382
367
|
|
|
383
|
-
def
|
|
368
|
+
def start_process(self, name: str):
|
|
384
369
|
cmd = CodeBlock('start_process', data={'id': 'block', 'block': 'start_process', 'data': name})
|
|
385
|
-
self.
|
|
370
|
+
self.codeblocks.append(cmd)
|
|
386
371
|
|
|
387
372
|
|
|
388
|
-
def
|
|
389
|
-
args =
|
|
373
|
+
def player_action(self, name: str, *args, target: Target=DEFAULT_TARGET):
|
|
374
|
+
args = _convert_data_types(args)
|
|
390
375
|
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'player_action', 'action': name})
|
|
391
|
-
self.
|
|
376
|
+
self.codeblocks.append(cmd)
|
|
392
377
|
|
|
393
378
|
|
|
394
|
-
def
|
|
395
|
-
args =
|
|
379
|
+
def game_action(self, name: str, *args):
|
|
380
|
+
args = _convert_data_types(args)
|
|
396
381
|
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'game_action', 'action': name})
|
|
397
|
-
self.
|
|
382
|
+
self.codeblocks.append(cmd)
|
|
398
383
|
|
|
399
384
|
|
|
400
|
-
def
|
|
401
|
-
args =
|
|
385
|
+
def entity_action(self, name: str, *args, target: Target=DEFAULT_TARGET):
|
|
386
|
+
args = _convert_data_types(args)
|
|
402
387
|
cmd = CodeBlock(name, args, target=target, data={'id': 'block', 'block': 'entity_action', 'action': name})
|
|
403
|
-
self.
|
|
388
|
+
self.codeblocks.append(cmd)
|
|
404
389
|
|
|
405
390
|
|
|
406
|
-
def
|
|
407
|
-
args =
|
|
391
|
+
def if_player(self, name: str, *args, target: Target=DEFAULT_TARGET, inverted: bool=False):
|
|
392
|
+
args = _convert_data_types(args)
|
|
408
393
|
data = {'id': 'block', 'block': 'if_player', 'action': name}
|
|
409
|
-
|
|
394
|
+
_add_inverted(data, inverted)
|
|
410
395
|
cmd = CodeBlock(name, args, target=target, data=data)
|
|
411
|
-
self.
|
|
396
|
+
self.codeblocks.append(cmd)
|
|
412
397
|
self._openbracket()
|
|
413
398
|
|
|
414
399
|
|
|
415
|
-
def
|
|
416
|
-
args =
|
|
400
|
+
def if_variable(self, name: str, *args, inverted: bool=False):
|
|
401
|
+
args = _convert_data_types(args)
|
|
417
402
|
data = {'id': 'block', 'block': 'if_var', 'action': name}
|
|
418
|
-
|
|
403
|
+
_add_inverted(data, inverted)
|
|
419
404
|
cmd = CodeBlock(name, args, data=data)
|
|
420
|
-
self.
|
|
405
|
+
self.codeblocks.append(cmd)
|
|
421
406
|
self._openbracket()
|
|
422
407
|
|
|
423
408
|
|
|
424
|
-
def
|
|
425
|
-
args =
|
|
409
|
+
def if_game(self, name: str, *args, inverted: bool=False):
|
|
410
|
+
args = _convert_data_types(args)
|
|
426
411
|
data = {'id': 'block', 'block': 'if_game', 'action': name}
|
|
427
|
-
|
|
412
|
+
_add_inverted(data, inverted)
|
|
428
413
|
cmd = CodeBlock(name, args, data=data)
|
|
429
|
-
self.
|
|
414
|
+
self.codeblocks.append(cmd)
|
|
430
415
|
self._openbracket()
|
|
431
416
|
|
|
432
417
|
|
|
433
|
-
def
|
|
434
|
-
args =
|
|
418
|
+
def if_entity(self, name: str, *args, target: Target=DEFAULT_TARGET, inverted: bool=False):
|
|
419
|
+
args = _convert_data_types(args)
|
|
435
420
|
data = {'id': 'block', 'block': 'if_entity', 'action': name}
|
|
436
|
-
|
|
421
|
+
_add_inverted(data, inverted)
|
|
437
422
|
cmd = CodeBlock(name, args, target=target, data=data)
|
|
438
|
-
self.
|
|
423
|
+
self.codeblocks.append(cmd)
|
|
439
424
|
self._openbracket()
|
|
440
425
|
|
|
441
426
|
|
|
442
427
|
def else_(self):
|
|
443
428
|
cmd = CodeBlock('else', data={'id': 'block', 'block': 'else'})
|
|
444
|
-
self.
|
|
429
|
+
self.codeblocks.append(cmd)
|
|
445
430
|
self._openbracket()
|
|
446
431
|
|
|
447
432
|
|
|
448
|
-
def repeat(self, name: str, *args,
|
|
449
|
-
args =
|
|
433
|
+
def repeat(self, name: str, *args, sub_action: str=None):
|
|
434
|
+
args = _convert_data_types(args)
|
|
450
435
|
data = {'id': 'block', 'block': 'repeat', 'action': name}
|
|
451
|
-
if
|
|
452
|
-
data['subAction'] =
|
|
436
|
+
if sub_action is not None:
|
|
437
|
+
data['subAction'] = sub_action
|
|
453
438
|
cmd = CodeBlock(name, args, data=data)
|
|
454
|
-
self.
|
|
439
|
+
self.codeblocks.append(cmd)
|
|
455
440
|
self._openbracket('repeat')
|
|
456
441
|
|
|
457
442
|
|
|
458
443
|
def bracket(self, *args):
|
|
459
|
-
args =
|
|
460
|
-
cmd = CodeBlock('
|
|
461
|
-
self.
|
|
444
|
+
args = _convert_data_types(args)
|
|
445
|
+
cmd = CodeBlock('bracket', data={'id': 'bracket', 'direct': 'close', 'type': self.bracket_stack.pop()})
|
|
446
|
+
self.codeblocks.append(cmd)
|
|
462
447
|
|
|
463
448
|
|
|
464
449
|
def control(self, name: str, *args):
|
|
465
|
-
args =
|
|
450
|
+
args = _convert_data_types(args)
|
|
466
451
|
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'control', 'action': name})
|
|
467
|
-
self.
|
|
452
|
+
self.codeblocks.append(cmd)
|
|
468
453
|
|
|
469
454
|
|
|
470
|
-
def
|
|
471
|
-
args =
|
|
455
|
+
def select_object(self, name: str, *args):
|
|
456
|
+
args = _convert_data_types(args)
|
|
472
457
|
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'select_obj', 'action': name})
|
|
473
|
-
self.
|
|
458
|
+
self.codeblocks.append(cmd)
|
|
474
459
|
|
|
475
460
|
|
|
476
|
-
def
|
|
477
|
-
args =
|
|
461
|
+
def set_variable(self, name: str, *args):
|
|
462
|
+
args = _convert_data_types(args)
|
|
478
463
|
cmd = CodeBlock(name, args, data={'id': 'block', 'block': 'set_var', 'action': name})
|
|
479
|
-
self.
|
|
464
|
+
self.codeblocks.append(cmd)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def generate_script(self, output_path: str, indent_size: int=4, literal_shorthand: bool=True, var_shorthand: bool=False):
|
|
468
|
+
"""
|
|
469
|
+
Generate an equivalent python script for this template.
|
|
470
|
+
|
|
471
|
+
:param str output_path: The file path to write the script to.
|
|
472
|
+
:param int indent_size: The multiple of spaces to add when indenting lines.
|
|
473
|
+
:param bool literal_shorthand: If True, `text` and `num` items will be written as strings and ints respectively.
|
|
474
|
+
:param bool var_shorthand: If True, all variables will be written using variable shorthand.
|
|
475
|
+
"""
|
|
476
|
+
flags = GeneratorFlags(indent_size, literal_shorthand, var_shorthand)
|
|
477
|
+
with open(output_path, 'w') as f:
|
|
478
|
+
f.write(generate_script(self, flags))
|
|
479
|
+
|