Skip to content

Commit 2586889

Browse files
authored
Merge pull request #3 from Slackow/dev
Version 0.1.4
2 parents 97ce7a1 + ea1702d commit 2586889

2 files changed

Lines changed: 53 additions & 34 deletions

File tree

README.md

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,24 @@ multiple `anon/function`'s take up names like `anon/function_1`, `anon/function_
9393

9494
ex:
9595
```
96-
=== data/main/sources/main.dps ===
96+
=== data/main/source/main.dps ===
9797
/function tick [tick]:
9898
/data modify storage args msg set value "example"
9999
/execute as @a run function main:func [] with storage args:
100100
/$say $(msg)
101101
```
102102
outputs
103103
```
104-
=== data/main/functions/tick.mcfunction ===
105-
# Generated by PackScript 0.1.0
104+
=== data/main/function/tick.mcfunction ===
105+
# Generated by PackScript 0.1.4
106106
data modify storage args msg set value "example"
107107
execute as @a run function main:func with storage args
108108
109-
=== data/main/functions/func.mcfunction ===
110-
# Generated by PackScript 0.1.0
109+
=== data/main/function/func.mcfunction ===
110+
# Generated by PackScript 0.1.4
111111
$say $(msg)
112112
113-
=== data/minecraft/tags/functions/tick.json ===
113+
=== data/minecraft/tags/function/tick.json ===
114114
{
115115
"values": [
116116
"main:tick"
@@ -144,8 +144,8 @@ this is done with Python's builtin JSON library.<br>
144144
a String or Bytes object will just be written raw to the file, but I do not know what this would be useful for.
145145

146146
```
147-
=== data/main/sources/main.dps ===
148-
create tags/blocks ns:chests -> {
147+
=== data/main/source/main.dps ===
148+
create tags/block ns:chests -> {
149149
"values": [
150150
"chest",
151151
"trapped_chest",
@@ -155,7 +155,7 @@ create tags/blocks ns:chests -> {
155155
```
156156
outputs
157157
```
158-
=== data/ns/tags/blocks/chests.json ===
158+
=== data/ns/tags/block/chests.json ===
159159
{
160160
"values": [
161161
"chest",
@@ -170,7 +170,7 @@ Of course, you do not need to specify a literal dictionary right after.
170170
def tag(*values):
171171
return {"values": values}
172172
173-
create tags/blocks chests -> \
173+
create tags/block chests -> \
174174
tag('chest', 'trapped_chest', 'ender_chest')
175175
```
176176

@@ -180,7 +180,7 @@ The capture_lines() function diverts command lines to a list of strings instead
180180
This is niche, but useful for constructing 'Only One Command's.
181181

182182
```
183-
=== data/ooc/sources/main.dps ===
183+
=== data/ooc/source/main.dps ===
184184
def only_one_command(definer):
185185
""" Generates "Only One Command"s given a function that defines commands """
186186
with capture_lines() as lines:
@@ -203,14 +203,14 @@ def only_one_command(definer):
203203
```
204204
outputs
205205
```
206-
=== data/ooc/functions/ooc.mcfunction ===
207-
# Generated by PackScript 0.1.0
206+
=== data/ooc/function/ooc.mcfunction ===
207+
# Generated by PackScript 0.1.4
208208
summon falling_block ~ ~1 ~ {BlockState:{Name:redstone_block},Passengers:[{id:falling_block,BlockState:{Name:activator_rail}},{id:command_block_minecart,Command:'gamerule commandBlockOutput false'},{id:command_block_minecart,Command:'say as second lame command'},{id:command_block_minecart,Command:'say third lamer command lol'},{id:command_block_minecart,Command:'tellraw @a "look ma I\'m using quotes \\\\/!"'},{id:command_block_minecart,Command:'tellraw @a[name=!"Slackow"] "say \\"lol\\""'},{id:command_block_minecart,Command:'setblock ~ ~1 ~ command_block{auto:1b,Command:"fill ~ ~ ~ ~ ~-3 ~ air"}'},{id:command_block_minecart,Command:'kill @e[type=command_block_minecart,distance=..1]'}]}
209209
```
210210
## `ns` String
211211
The `ns` global variable lets you access the namespace of the dps file you are in as a string. note that `ns` is the namespace of the *source* file, not the function you are in.
212212
```
213-
=== data/example_pack/sources/example.dps ===
213+
=== data/example_pack/source/example.dps ===
214214
/function say_something:
215215
/say something!
216216
/function example:
@@ -219,11 +219,11 @@ The `ns` global variable lets you access the namespace of the dps file you are i
219219
```
220220
outputs
221221
```
222-
=== data/example_pack/functions/say_something.mcfunction ===
223-
# Generated by PackScript 0.1.2
222+
=== data/example_pack/function/say_something.mcfunction ===
223+
# Generated by PackScript 0.1.4
224224
say something!
225-
=== data/example_pack/functions/example.mcfunction ===
226-
# Generated by PackScript 0.1.2
225+
=== data/example_pack/function/example.mcfunction ===
226+
# Generated by PackScript 0.1.4
227227
function example_pack:say_something
228228
```
229229

@@ -281,12 +281,14 @@ add lines or create new files.
281281
# FunctionPackScript
282282
Most files shown so far have been `.dps` files, standing for DataPackScript,
283283
but there's also FunctionPackScript with `.fps` files. These are contained in the root of the input directory instead
284-
of under a proper datapack with a namespace underneath sources, these are meant for generating independent
284+
of under a proper datapack with a namespace underneath `source`[<sup>[1]</sup>](#f1), these are meant for generating independent
285285
function files easily, usually those with repetitive lines. In these files you cannot use create statements, but you can generate
286286
additional functions. All the generated function files
287287
will have their namespace ignored and be generated in the same directory
288288
as the main generated function.
289289

290+
<span id="f1">[1]</span>: In older versions of minecraft (pre 1.21) this folder is `sources` instead. PackScript will automatically figure out which folder name to use based on your pack_format value in your `pack.mcmeta`.
291+
290292
# The CLI
291293
This tool has two main actions it can perform: compiling packs and initializing templates.
292294
- `python3 packscript.py c` (you can also use compile or comp)
@@ -300,7 +302,7 @@ More actions:
300302
## Compile Options
301303
- `-i/--input <dir>` specify the directory of the pack you are compiling defaults to current dir.
302304
- `-o/--output <dir/zip>` specify the output of the pack (can output zip too) defaults to `output`
303-
- `-s/--sources` output the source files into the resulting pack, by default they get deleted
305+
- `-s/--source` output the source files into the resulting pack, by default they get deleted
304306
- `-v/--verbose` print out all the generated Python code with line numbers. Very good for debugging.
305307

306308
## Init Options
@@ -350,6 +352,6 @@ In this case it's because there's a letter before the command line, making it ge
350352
4. **Create A Datapack.** Run `python3 packscript.py init` in order to create a datapack with
351353
PackScript. You'll be prompted for information about the datapack.
352354
You should have a new datapack, you can put files in there as usual for them to
353-
be outputted, files in `<pack>/data/*/sources/*.dps` and `<pack>/*.fps` will be interpreted as PackScript
355+
be outputted, files in `<pack>/data/*/source/*.dps` and `<pack>/*.fps` will be interpreted as PackScript
354356
on compilation. By default, you will find a main.dps file there.
355357
5. **Compile Datapack.** To compile, run `python3 packscript.py compile -i <datapack directory> -o <output>`

packscript.py

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import shutil
77
import sys
88

9-
__version__ = '0.1.3'
10-
latest_mc_version = '1.20.6'
9+
__version__ = '0.1.4'
10+
latest_mc_version = '1.21'
1111

1212
# # # # # # # # # # # # # # # # # # # # # #
1313
# Please set this to your username if you are modifying this script
@@ -20,6 +20,7 @@ def ver(base_version, start, end, *, pf):
2020

2121

2222
pack_formats = {
23+
'1.21': 48,
2324
'1.20.6': 41, '1.20.5': 41,
2425
'1.20.4': 26, '1.20.3': 26, '1.20.2': 18,
2526
'1.20.1': 15, '1.20': 15, '1.19.4': 12,
@@ -186,11 +187,15 @@ def capture_lines():
186187
return globals
187188

188189

189-
def get_header():
190+
def get_header() -> str:
190191
return f'# Generated by PackScript {__version__}{modified_by and f" modified by: {modified_by}"}\n'
191192

192193

193-
def comp(*, input, output, verbose, sources, **_):
194+
def get_folder(path: str, pf: int) -> str:
195+
return path if pf >= 45 else path + 's'
196+
197+
198+
def comp(*, input: str, output: str, verbose: bool, source: bool, **_):
194199
try:
195200
namespaces = os.listdir(os.path.join(input, 'data'))
196201

@@ -213,21 +218,32 @@ def comp(*, input, output, verbose, sources, **_):
213218
os.path.join(output_folder, 'pack.png'))
214219
else:
215220
raise FileNotFoundError('need data folder and pack.mcmeta')
221+
# Thanks, boq.
222+
with open(os.path.join(input, 'pack.mcmeta')) as f:
223+
pack_meta = json.load(f)
224+
if not pack_meta or not isinstance(pack_meta.get('pack'), dict):
225+
raise ValueError('Invalid pack.mcmeta file')
226+
pack_format = pack_meta.get('pack').get('pack_format')
227+
if not isinstance(pack_format, int):
228+
raise ValueError('Invalid pack.mcmeta file')
216229

217230
function_tags: dict[str, list[str]] = {}
218231
other: dict[str, dict[str, object]] = {}
219232
for namespace in sorted(namespaces):
220233
try:
221-
if not sources:
222-
shutil.rmtree(os.path.join(output_folder, 'data', namespace, 'sources'))
234+
if not source:
235+
shutil.rmtree(os.path.join(output_folder, 'data', namespace, get_folder('source', pack_format)))
223236
except IOError:
224237
continue
225238
func_files: dict[str, list[str]] = {'': []}
226239
func_stack: list[str] = ['']
227240
capturer_stack: list[str] = []
228241

229242
globals = build_globals(func_stack, capturer_stack, func_files, other, namespace, function_tags)
230-
working_folder = os.path.join(input, f'data/{namespace}/sources')
243+
working_folder = os.path.join(input, f'data/{namespace}/{get_folder('source', pack_format)}')
244+
if (not get_folder('source', pack_format).endswith('s') and
245+
os.path.exists(os.path.join(working_folder, f'data/{namespace}/sources'))):
246+
raise ValueError('Legacy "sources" folder detected! Rename your folders to be singular!')
231247
try:
232248
for filename in os.listdir(working_folder):
233249
if filename.endswith(f'.{DATA_EXT}'):
@@ -238,7 +254,8 @@ def comp(*, input, output, verbose, sources, **_):
238254
func_files.pop('')
239255
# Iterate through generated functions
240256
for name, content in func_files.items():
241-
mcfunction_path = os.path.join(output_folder, f'data/{name.replace(":", "/functions/")}.mcfunction')
257+
func_dir = get_folder('function', pack_format)
258+
mcfunction_path = os.path.join(output_folder, f'data/{name.replace(":", f"/{func_dir}/")}.mcfunction')
242259
if not content:
243260
continue
244261
try:
@@ -250,7 +267,7 @@ def comp(*, input, output, verbose, sources, **_):
250267

251268
# <editor-fold defaultstate="collapsed" desc="Move function tags into 'other' dictionary">
252269

253-
other.setdefault('tags/functions', {}).update(
270+
other.setdefault(f'tags/{get_folder("function", pack_format)}', {}).update(
254271
{tag: {'values': func_names} for tag, func_names in function_tags.items()})
255272

256273
# </editor-fold>
@@ -329,12 +346,12 @@ def init_template(*, name: str, description: str, pack_format: int, output: str,
329346
description = description or input(f'Description (Datapack {name!r}{v}): ') or \
330347
f'Datapack {name!r}{v}'
331348
output = output or input(f'Output Directory ({name.replace(" ", "_")}): ') or name.replace(' ', '_')
332-
sources = os.path.join(output, f'data/{namespace}/sources')
349+
source = os.path.join(output, f'data/{namespace}/{get_folder("source", pf=pack_format)}')
333350
try:
334-
os.makedirs(sources)
351+
os.makedirs(source)
335352
except FileExistsError:
336353
pass
337-
with open(os.path.join(os.path.join(sources, f'main.{DATA_EXT}')), 'w') as w:
354+
with open(os.path.join(os.path.join(source, f'main.{DATA_EXT}')), 'w') as w:
338355
import inspect
339356
w.write(inspect.cleandoc(f'''
340357
/function tick [tick]:
@@ -431,7 +448,7 @@ def main():
431448
parser_compile.add_argument('-i', '--input', type=str, help='Input directory', default='.')
432449
parser_compile.add_argument('-v', '--verbose', help='Print generated Python code.', default=False,
433450
action='store_true')
434-
parser_compile.add_argument('-S', '--sources', help='Include source files in output.', default=False,
451+
parser_compile.add_argument('-S', '--source', help='Include source files in output.', default=False,
435452
action='store_true')
436453

437454
# "init" command

0 commit comments

Comments
 (0)