dfpyre 0.7.11__py3-none-any.whl → 0.8.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/pyre.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- A package for externally creating code templates for the DiamondFire Minecraft server.
2
+ A package for making code templates for the DiamondFire Minecraft server.
3
3
 
4
4
  By Amp
5
5
  """
@@ -7,9 +7,7 @@ By Amp
7
7
  import json
8
8
  from difflib import get_close_matches
9
9
  import datetime
10
- from typing import Tuple
11
10
  from enum import Enum
12
- import socket
13
11
  from mcitemlib.itemlib import Item as NbtItem
14
12
  from dfpyre.util import *
15
13
  from dfpyre.items import *
@@ -46,57 +44,90 @@ class Target(Enum):
46
44
  DEFAULT_TARGET = Target.SELECTION
47
45
 
48
46
 
47
+ def _convert_args(args):
48
+ return tuple(map(convert_argument, args))
49
+
50
+
49
51
  class CodeBlock:
50
- def __init__(self, name: str, args: Tuple=(), target: Target=DEFAULT_TARGET, data: dict={}, tags: dict[str, str]={}):
51
- self.name = name
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
52
55
  self.args = args
53
56
  self.target = target
54
57
  self.data = data
55
58
  self.tags = tags
56
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
+
57
98
  def __repr__(self) -> str:
58
- if self.name == 'dynamic':
99
+ if self.action_name == 'dynamic':
59
100
  return f'CodeBlock({self.data["block"]}, {self.data["data"]})'
60
- if self.name == 'else':
101
+ if self.action_name == 'else':
61
102
  return 'CodeBlock(else)'
62
103
  if 'block' in self.data:
63
- return f'CodeBlock({self.data["block"]}, {self.name})'
104
+ return f'CodeBlock({self.data["block"]}, {self.action_name})'
64
105
  return f'CodeBlock(bracket, {self.data["type"]}, {self.data["direct"]})'
65
106
 
66
- def __eq__(self, value):
67
- if not isinstance(value, CodeBlock):
68
- return False
69
- return self.name == value.name and \
70
- self.args == value.args and \
71
- self.target == value.target and \
72
- self.data == value.data and \
73
- self.tags == value.tags
74
107
 
75
108
  def build(self, include_tags: bool=True) -> dict:
76
109
  """
77
110
  Builds a properly formatted block from a CodeBlock object.
78
111
  """
79
112
  built_block = self.data.copy()
80
- codeblock_type = self.data.get('block')
81
113
 
82
114
  # add target if necessary ('Selection' is the default when 'target' is blank)
83
- if codeblock_type in TARGET_CODEBLOCKS and self.target != DEFAULT_TARGET:
115
+ if self.type in TARGET_CODEBLOCKS and self.target != DEFAULT_TARGET:
84
116
  built_block['target'] = self.target.get_string_value()
85
117
 
86
118
  # add items into args
87
119
  final_args = [arg.format(slot) for slot, arg in enumerate(self.args) if arg.type in VARIABLE_TYPES]
88
120
 
89
121
  # check for unrecognized name, add tags
90
- if codeblock_type is not None and codeblock_type != 'else':
91
- if self.name not in CODEBLOCK_DATA[codeblock_type]:
92
- _warn_unrecognized_name(codeblock_type, self.name)
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)
93
125
  elif include_tags:
94
- tags = _get_codeblock_tags(codeblock_type, self.name, self.tags)
126
+ tags = _get_codeblock_tags(self.type, self.action_name, self.tags)
95
127
  if len(final_args) + len(tags) > 27:
96
128
  final_args = final_args[:(27-len(tags))] # trim list if over 27 elements
97
129
  final_args.extend(tags) # add tags to end
98
-
99
- # if final_args:
130
+
100
131
  built_block['args'] = {'items': final_args}
101
132
  return built_block
102
133
 
@@ -109,22 +140,11 @@ def _warn_unrecognized_name(codeblock_type: str, codeblock_name: str):
109
140
  warn(f'Code block name "{codeblock_name}" not recognized. Try spell checking or retyping without spaces.')
110
141
 
111
142
 
112
- def _add_inverted(data, inverted):
113
- """
114
- If inverted is true, add 'inverted': 'NOT' to data.
115
- """
116
- if inverted:
117
- data['inverted'] = 'NOT'
118
-
119
-
120
- def _convert_args(args):
121
- return tuple(map(convert_argument, args))
122
-
123
-
124
143
  def _check_applied_tags(tags: list[dict], applied_tags: dict[str, str], codeblock_name: str) -> dict[str, str]:
125
144
  if len(applied_tags) > 0 and len(tags) == 0:
126
145
  warn(f'Action "{codeblock_name}" does not have any tags, but still received {len(applied_tags)}.')
127
146
  return {}
147
+
128
148
  valid_tags = {}
129
149
  tags_formatted = {t['name']: t for t in tags}
130
150
  for name, option in applied_tags.items():
@@ -139,12 +159,21 @@ def _check_applied_tags(tags: list[dict], applied_tags: dict[str, str], codebloc
139
159
  return valid_tags
140
160
 
141
161
 
142
- def _reformat_codeblock_tags(tags: list[dict], codeblock_type: str, codeblock_name: str, applied_tags: dict[str, str]):
162
+ def _reformat_codeblock_tags(tags: list[dict], codeblock_type: str, codeblock_action: str, applied_tags: dict[str, str]):
143
163
  """
144
164
  Turns tag objects into DiamondFire formatted tag items
145
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
+ }
146
175
 
147
- valid_applied_tags = _check_applied_tags(tags, applied_tags, codeblock_name)
176
+ valid_applied_tags = _check_applied_tags(tags, applied_tags, codeblock_action)
148
177
  reformatted_tags = []
149
178
  for tag_item in tags:
150
179
  tag_name = tag_item['name']
@@ -152,18 +181,7 @@ def _reformat_codeblock_tags(tags: list[dict], codeblock_type: str, codeblock_na
152
181
  if tag_name in valid_applied_tags:
153
182
  tag_option = valid_applied_tags[tag_name]
154
183
 
155
- new_tag_item = {
156
- 'item': {
157
- 'id': 'bl_tag',
158
- 'data': {
159
- 'option': tag_option,
160
- 'tag': tag_name,
161
- 'action': codeblock_name,
162
- 'block': codeblock_type
163
- }
164
- },
165
- 'slot': tag_item['slot']
166
- }
184
+ new_tag_item = format_tag(tag_option, tag_name)
167
185
  reformatted_tags.append(new_tag_item)
168
186
  return reformatted_tags
169
187
 
@@ -205,15 +223,21 @@ class DFTemplate:
205
223
  """
206
224
  Represents a DiamondFire code template.
207
225
  """
208
- def __init__(self, name: str=None, author: str='pyre'):
209
- self.codeblocks: list[CodeBlock] = []
210
- self.bracket_stack: list[str] = []
211
- self.name = name
226
+ def __init__(self, codeblocks: list[CodeBlock], author: str='pyre'):
227
+ self.codeblocks = codeblocks
212
228
  self.author = author
213
229
 
214
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
+
215
239
  def __repr__(self) -> str:
216
- return f'DFTemplate(name: {self.name}, author: {self.author}, codeblocks: {len(self.codeblocks)})'
240
+ return f'DFTemplate(name: "{self._get_template_name()}", author: "{self.author}", codeblocks: {len(self.codeblocks)})'
217
241
 
218
242
 
219
243
  @staticmethod
@@ -222,47 +246,54 @@ class DFTemplate:
222
246
  Create a template object from an existing template code.
223
247
  """
224
248
  template_dict = json.loads(df_decode(template_code))
225
- template = DFTemplate()
226
- template._set_template_name(template_dict['blocks'][0])
249
+ codeblocks: list[CodeBlock] = []
227
250
  for block_dict in template_dict['blocks']:
228
251
  block_tags = get_default_tags(block_dict.get('block'), block_dict.get('action'))
229
252
  if 'args' in block_dict:
230
- args = []
253
+ block_args = []
231
254
  for item_dict in block_dict['args']['items']:
232
255
  if item_dict['item'].get('id') == 'bl_tag':
233
256
  tag_data = item_dict['item']['data']
234
257
  block_tags[tag_data['tag']] = tag_data['option']
235
258
  parsed_item = item_from_dict(item_dict['item'])
236
259
  if parsed_item is not None:
237
- args.append(parsed_item)
238
- target = Target(TARGETS.index(block_dict['target'])) if 'target' in block_dict else DEFAULT_TARGET
239
-
240
- codeblock_action = 'bracket'
241
- if block_dict.get('block') == 'else':
242
- codeblock_action = 'else'
243
- elif block_dict.get('block') in DYNAMIC_CODEBLOCKS:
244
- codeblock_action = 'dynamic'
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)
245
271
  elif 'action' in block_dict:
246
- codeblock_action = block_dict['action']
247
-
248
- if codeblock_action == 'bracket' or block_dict['block'] == 'else':
249
- codeblock = CodeBlock(codeblock_action, data=block_dict)
250
- else:
251
- codeblock = CodeBlock(codeblock_action, args, target, block_dict, tags=block_tags)
252
- template.codeblocks.append(codeblock)
272
+ codeblock = CodeBlock.new_action(codeblock_type, block_dict['action'], block_args, block_tags, block_target)
273
+ codeblocks.append(codeblock)
253
274
 
254
- return template
275
+ return DFTemplate(codeblocks)
255
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`.
256
281
 
257
- def _set_template_name(self, first_block):
258
- if self.name is not None:
259
- return
260
- if 'data' in first_block:
261
- self.name = first_block['data']
262
- if not self.name:
263
- self.name = 'Unnamed Template'
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)
264
294
  else:
265
- self.name = first_block['block'] + '_' + first_block['action']
295
+ raise PyreException('Expected CodeBlock or list[CodeBlock] to insert.')
296
+ return self
266
297
 
267
298
 
268
299
  def build(self, include_tags: bool=True) -> str:
@@ -278,8 +309,6 @@ class DFTemplate:
278
309
  if first_block['block'] not in TEMPLATE_STARTERS:
279
310
  warn('Template does not start with an event, function, or process.')
280
311
 
281
- self._set_template_name(first_block)
282
-
283
312
  json_string = json.dumps(template_dict, separators=(',', ':'))
284
313
  return df_encode(json_string)
285
314
 
@@ -291,168 +320,135 @@ class DFTemplate:
291
320
  :param bool include_tags: If True, include item tags in code blocks. Otherwise omit them.
292
321
  """
293
322
  template_code = self.build(include_tags)
294
- template_item = _get_template_item(template_code, self.name, self.author)
323
+ template_item = _get_template_item(template_code, self._get_template_name(), self.author)
295
324
  return template_item.send_to_minecraft(method, 'pyre')
296
325
 
297
-
298
- def clear(self):
326
+
327
+ def generate_script(self, output_path: str, indent_size: int=4, literal_shorthand: bool=True, var_shorthand: bool=False):
299
328
  """
300
- Clears this template's data.
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.
301
335
  """
302
- self.__init__()
303
-
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))
304
339
 
305
- def _add_codeblock(self, codeblock: CodeBlock, index: int|None):
306
- if index is None:
307
- self.codeblocks.append(codeblock)
308
- else:
309
- self.codeblocks.insert(index, codeblock)
310
-
311
340
 
312
- def _openbracket(self, index: int|None, btype: Literal['norm', 'repeat']='norm'):
313
- bracket = CodeBlock('bracket', data={'id': 'bracket', 'direct': 'open', 'type': btype})
314
- self._add_codeblock(bracket, index)
315
- self.bracket_stack.append(btype)
316
-
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)
317
350
 
318
- # command methods
319
- def player_event(self, name: str, index: int|None=None):
320
- cmd = CodeBlock(name, data={'id': 'block', 'block': 'event', 'action': name})
321
- self._add_codeblock(cmd, index)
322
-
323
351
 
324
- def entity_event(self, name: str, index: int|None=None):
325
- cmd = CodeBlock(name, data={'id': 'block', 'block': 'entity_event', 'action': name})
326
- self._add_codeblock(cmd, index)
327
-
352
+ def player_event(event_name: str, codeblocks: list[CodeBlock]=(), author: str|None=None) -> DFTemplate:
353
+ starting_block = CodeBlock.new_action('event', event_name, (), {})
354
+ return _assemble_template(starting_block, codeblocks, author)
328
355
 
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)
332
- self._add_codeblock(cmd, index)
333
-
334
356
 
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)
338
- self._add_codeblock(cmd, index)
339
-
357
+ def entity_event(event_name: str, codeblocks: list[CodeBlock]=[], author: str|None=None) -> DFTemplate:
358
+ starting_block = CodeBlock.new_action('entity_event', event_name, (), {})
359
+ return _assemble_template(starting_block, codeblocks, author)
340
360
 
341
- def call_function(self, name: str, *args, index: int|None=None):
342
- args = _convert_args(args)
343
- cmd = CodeBlock('dynamic', args, data={'id': 'block', 'block': 'call_func', 'data': name})
344
- self._add_codeblock(cmd, index)
345
361
 
362
+ def function(function_name: str, *args, tags: dict[str, str]={}, codeblocks: list[CodeBlock]=[], author: str|None=None) -> DFTemplate:
363
+ starting_block = CodeBlock.new_data('func', function_name, args, tags)
364
+ return _assemble_template(starting_block, codeblocks, author)
346
365
 
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)
349
- self._add_codeblock(cmd, index)
350
366
 
367
+ def process(process_name: str, *args, tags: dict[str, str]={}, codeblocks: list[CodeBlock]=[], author: str|None=None) -> DFTemplate:
368
+ starting_block = CodeBlock.new_data('process', process_name, args, tags)
369
+ return _assemble_template(starting_block, codeblocks, author)
351
370
 
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)
355
- self._add_codeblock(cmd, index)
356
-
357
371
 
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)
361
- self._add_codeblock(cmd, index)
362
-
372
+ def call_function(function_name: str, *args) -> CodeBlock:
373
+ return CodeBlock.new_data('call_func', function_name, args, {})
363
374
 
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)
367
- self._add_codeblock(cmd, index)
368
-
369
375
 
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)
372
- data = {'id': 'block', 'block': 'if_player', 'action': name}
373
- _add_inverted(data, inverted)
374
- cmd = CodeBlock(name, args, target=target, data=data, tags=tags)
375
- self._add_codeblock(cmd, index)
376
- self._openbracket(index)
377
-
376
+ def start_process(process_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
377
+ return CodeBlock.new_data('start_process', process_name, args, tags)
378
378
 
379
- def if_variable(self, name: str, *args, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
380
- args = _convert_args(args)
381
- data = {'id': 'block', 'block': 'if_var', 'action': name}
382
- _add_inverted(data, inverted)
383
- cmd = CodeBlock(name, args, data=data, tags=tags)
384
- self._add_codeblock(cmd, index)
385
- self._openbracket(index)
386
-
387
379
 
388
- def if_game(self, name: str, *args, tags: dict[str, str]={}, inverted: bool=False, index: int|None=None):
389
- args = _convert_args(args)
390
- data = {'id': 'block', 'block': 'if_game', 'action': name}
391
- _add_inverted(data, inverted)
392
- cmd = CodeBlock(name, args, data=data, tags=tags)
393
- self._add_codeblock(cmd, index)
394
- self._openbracket(index)
395
-
380
+ def player_action(action_name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}) -> CodeBlock:
381
+ return CodeBlock.new_action('player_action', action_name, args, tags, target=target)
396
382
 
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)
399
- data = {'id': 'block', 'block': 'if_entity', 'action': name}
400
- _add_inverted(data, inverted)
401
- cmd = CodeBlock(name, args, target=target, data=data, tags=tags)
402
- self._add_codeblock(cmd, index)
403
- self._openbracket(index)
404
383
 
384
+ def entity_action(action_name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}) -> CodeBlock:
385
+ return CodeBlock.new_action('entity_action', action_name, args, tags, target=target)
405
386
 
406
- def else_(self, index: int|None=None):
407
- cmd = CodeBlock('else', data={'id': 'block', 'block': 'else'})
408
- self._add_codeblock(cmd, index)
409
- self._openbracket(index)
410
-
411
387
 
412
- def repeat(self, name: str, *args, tags: dict[str, str]={}, sub_action: str=None, index: int|None=None):
413
- args = _convert_args(args)
414
- data = {'id': 'block', 'block': 'repeat', 'action': name}
415
- if sub_action is not None:
416
- data['subAction'] = sub_action
417
- cmd = CodeBlock(name, args, data=data, tags=tags)
418
- self._add_codeblock(cmd, index)
419
- self._openbracket(index, 'repeat')
388
+ def game_action(action_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
389
+ return CodeBlock.new_action('game_action', action_name, args, tags)
420
390
 
421
391
 
422
- def bracket(self, *args, index: int|None=None):
423
- args = _convert_args(args)
424
- cmd = CodeBlock('bracket', data={'id': 'bracket', 'direct': 'close', 'type': self.bracket_stack.pop()})
425
- self._add_codeblock(cmd, index)
426
-
392
+ def if_player(action_name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
393
+ return [
394
+ CodeBlock.new_conditional('if_player', action_name, args, tags, inverted, target),
395
+ CodeBlock.new_bracket('open', 'norm')
396
+ ] + list(codeblocks) + [
397
+ CodeBlock.new_bracket('close', 'norm')
398
+ ]
427
399
 
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)
431
- self._add_codeblock(cmd, index)
432
-
400
+ def if_entity(action_name: str, *args, target: Target=DEFAULT_TARGET, tags: dict[str, str]={}, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
401
+ return [
402
+ CodeBlock.new_conditional('if_entity', action_name, args, tags, inverted, target),
403
+ CodeBlock.new_bracket('open', 'norm')
404
+ ] + list(codeblocks) + [
405
+ CodeBlock.new_bracket('close', 'norm')
406
+ ]
433
407
 
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)
437
- self._add_codeblock(cmd, index)
438
-
439
408
 
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)
443
- self._add_codeblock(cmd, index)
444
-
445
-
446
- def generate_script(self, output_path: str, indent_size: int=4, literal_shorthand: bool=True, var_shorthand: bool=False):
447
- """
448
- Generate an equivalent python script for this template.
409
+ def if_game(action_name: str, *args, tags: dict[str, str]={}, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
410
+ return [
411
+ CodeBlock.new_conditional('if_game', action_name, args, tags, inverted),
412
+ CodeBlock.new_bracket('open', 'norm')
413
+ ] + list(codeblocks) + [
414
+ CodeBlock.new_bracket('close', 'norm')
415
+ ]
449
416
 
450
- :param str output_path: The file path to write the script to.
451
- :param int indent_size: The multiple of spaces to add when indenting lines.
452
- :param bool literal_shorthand: If True, `text` and `num` items will be written as strings and ints respectively.
453
- :param bool var_shorthand: If True, all variables will be written using variable shorthand.
454
- """
455
- flags = GeneratorFlags(indent_size, literal_shorthand, var_shorthand)
456
- with open(output_path, 'w', encoding='utf-8') as f:
457
- f.write(generate_script(self, flags))
458
-
417
+
418
+ def if_variable(action_name: str, *args, tags: dict[str, str]={}, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
419
+ return [
420
+ CodeBlock.new_conditional('if_var', action_name, args, tags, inverted),
421
+ CodeBlock.new_bracket('open', 'norm')
422
+ ] + list(codeblocks) + [
423
+ CodeBlock.new_bracket('close', 'norm')
424
+ ]
425
+
426
+
427
+ def else_(codeblocks: list[CodeBlock]=[]) -> list[CodeBlock]:
428
+ return [
429
+ CodeBlock.new_else(),
430
+ CodeBlock.new_bracket('open', 'norm')
431
+ ] + list(codeblocks) + [
432
+ CodeBlock.new_bracket('close', 'norm')
433
+ ]
434
+
435
+
436
+ def repeat(action_name: str, *args, tags: dict[str, str]={}, sub_action: str|None=None, inverted: bool=False, codeblocks: list[CodeBlock]=[]) -> CodeBlock:
437
+ return [
438
+ CodeBlock.new_repeat(action_name, args, tags, sub_action, inverted),
439
+ CodeBlock.new_bracket('open', 'repeat')
440
+ ] + list(codeblocks) + [
441
+ CodeBlock.new_bracket('close', 'repeat')
442
+ ]
443
+
444
+
445
+ def control(action_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
446
+ return CodeBlock.new_action('control', action_name, args, tags)
447
+
448
+
449
+ def select_object(action_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
450
+ return CodeBlock.new_action('select_obj', action_name, args, tags)
451
+
452
+
453
+ def set_variable(action_name: str, *args, tags: dict[str, str]={}) -> CodeBlock:
454
+ return CodeBlock.new_action('set_var', action_name, args, tags)