Minecraft Data Packs / Tool

Mcpy, an Mcfunction compiler

    • 4,881 views, 5 today
    • 102 downloads, 0 today
    • 27
    • 23
    • 17
    RevonZev's Avatar RevonZev
    Level 62 : High Grandmaster Dragon
    76
    Example Project:
    The example project is from my Poisonous Block Datapack except it's rewritten in MCPY

    MCPY is the programming language (".mcpy" file extension)
    The downloaded file is the compiler ("mcpy.exe" or "mcpy.py")

    If your computer tells you the program is a virus, it is not, if you download it from the above links or the above download button and in planetminecraft.com, or from my Github.


    MCPY

    Mcfunction compiler by using Python. This programming language is designed based on Mcfunction or Minecraft's commands, so moving from Mcfunction to Mcpy is easy. The file extension is ".mcpy" example: "main.mcpy"

    Up to date wiki

    Comment
    # This is a comment
    Note: Put a comment in its own line


    Normal Commands

    Normal commands are... just that, normal commands.
    say Hello World
    function test:main
    effect give @s minecraft:speed_boost 1 1
    summon minecraft:bat ~ ~ ~
    execute as @a at @s run say Hello Player


    Execute

    As At
    # A
    as at @a:
    say Hello World

    # B
    as @a:
    at @s:
    say Hello World

    # Compile into:
    execute as @a at @s run say Hello World

    Else
    if score @a home matches 0:
    say your score is 0
    else:
    say your score is not 0

    # Compile into:
    execute if score @a home matches 0 run say your score is 0
    execute unless score @a home matches 0 run say your score is not 0

    Other parts of execute
    The rest of the execute chain is the same as Minecraft, but with a ":" colon at the end.
    in nether:
    if block ~ ~ ~ fire:
    say Your burn is in a whole other dimensions

    # Compile into:
    execute in nether if block ~ ~ ~ fire run say Your burn is in whole other dimensions


    Scoreboard

    Define

    score home dummy "Display"

    # Compile into:
    scoreboard objectives add home dummy "Display"

    # DO NOT DO: score home dummy "Display" = 10

    Set
    home @a = 10
    home = 10

    # Compile into:
    scoreboard players set @a home 10
    scoreboard players set @s home 10

    Add
    home @a += 1
    home += 1

    # Compile into:
    scoreboard players add @a home 1
    scoreboard players add @s home 1

    Subtract
    home @a -= 1
    home -= 1

    # compile into:
    scoreboard players remove @a home 1
    scoreboard players remove @s home 1

    Operation
    home @a *= home @p
    home @a *= home
    home *= home @p
    home *= home

    # Compile into:
    scoreboard players operation @a home *= @p home
    scoreboard players operation @a home *= @s home
    scoreboard players operation @s home *= @p home
    scoreboard players operation @s home *= @s home

    # Operations: %=, *=, +=, -=, /=, <, >, =, ><

    Reset
    reset @p home

    # Compile into:
    scoreboard players reset @p home

    Store command result

    home @a := say Hello
    home := say Hello

    # Compile into
    execute store result score @a home run say Hello
    execute store result score @s home run say Hello

    Note
    # For selector arguments do not use space in it
    home @e[name=someone,tag=something] += 10
    # The below code do not work
    home @e[name=someone, tag=something] += 10

    # Compile into
    scoreboard players add @e[name=someone,tag=something] home 10
    scoreboard players add @e[name=someone, home tag=something]


    Function
    This is not Mcfunction! It is more like a snippet. Functions are globals. That means it is accessible within every file inside the project folder/path. Only one function per line and it has to be in its own line. It is recommended that you put your function before the call function line or put the functions inside "mcpy/-.mcpy".

    Define

    def print($msg):
    say $msg
    Note: You don't need to use $ before the variable.

    Call
    print("Hi")
    print("\"Hello\"")
    print(Heyo)

    # Compile into:
    say Hi
    say "Hello"
    say Heyo

    Nested function call as variables

    def saySomething($func,$msg):
    $func($msg)
    print(Hi)
    say Heyo

    saySomething(print,Hello)

    # Compile into:
    say Hello
    say Hi
    say Heyo
    Note: You need to use $ before the nested function call variable.


    For Loop
    for $i in [0, 2, 4]:
    unless score @a home matches $i:
    say your score is 0 or 2 or 4

    for $i in [1, 3, 5]:
    unless score @a home matches $i:
    say your score is $i

    for $i in [Hello, Hi, Heyo]:
    say $i

    Community's Functions
    Want to contribute to the community's functions? Put your function in the comment below and I'll check it out and put it here.

    Floor crafting by RevonZev:
    def craftHead($item,$count):
    as at @e[type=item,nbt={Item:{id:"minecraft:$item",Count:$countb}}]:

    def craft($item,$count):
    if entity @e[type=item,nbt={Item:{id:"minecraft:$item",Count:$countb}},distance=..1]:

    craftHead("milk_bucket",1)
    craft("ghast_tear",1)
    craft("nether_wart",1)
    function poisonous_block:crafting/antidote

    # Compile into:
    execute as @e[type=item,nbt={Item:{id:"minecraft:milk_bucket",Count:1b}}] at @s if entity @e[type=item,nbt={Item:{id:"minecraft:ghast_tear",Count:1b}},distance=..1] if entity @e[type=item,nbt={Item:{id:"minecraft:nether_wart",Count:1b}},distance=..1] run function poisonous_block:crafting/antidote

    Comparing scores shorthand by MrPlayerYork:
    def compare($object,$objective1,$op,$target,$objective2):
    if score $object $objective1 $op #$target $objective2:




    Obfuscation
    To generate a new obfuscation, delete "obfuscated_data.json". to turn on obfuscation in user_settings.json change keep_unused_obfuscated_string from false to true. Default: false


    Scoreboards
    In the user_settings.json if "obfuscate": true then instead of the variable name it will generate a random 16 character string. You can name the variables as long as you want. This will remove the scoreboards' display names.

    If "obfuscate": false you are limited in naming your variables to 16 characters (Minecraft's scoreboard objective name limit).

    Tags or strings
    To obfuscate a tag or string use
    obf tag_name

    Note: Any string that matches it will be obfuscated

    Keep the unused obfuscated string
    If keep_unused_obfuscated_string in user_settings.json is true then it will keep any unused obfuscated string from obfuscated_data.json, if it is false it will automatically remove any unused obfuscated string from obfuscated_data.json. Default: false


    User Settings
    The file is "user_settings.json"

    Watch delay
    The default is every 5 seconds. How much delay before it checks if a file has been modified and compiled. If set to 0, then it is on manual.

    Dist path
    The default is "./dist/". Dist location is in local. That means it cannot do "C:/Users/user/Documents/project/mcpy/dist" but instead "./dist/".
    WARNING: Files inside dist will get deleted.

    Project base path
    The default is "./mcpy/". Any Mcpy files that are inside the project base will be generated in the dist path.

    Tabbing style
    The default is 4 spaces. Do use the proper tabbing otherwise the compiler will not compile Mcpy to Mcfunction correctly.

    Keep comment
    The default is false. Keep comments written in mcpy in the compiled mcfunction.



    Any bugs you find or features you want, report them in the comments section below or on Github

    The MCPY compiler is © 2020 - 2021 Revon Zev. Any mcfunction / datapack you make with this is yours. Do not include the compiler when uploading your datapack. You may include the ".mcpy" files. Do not distribute the MCPY compiler.
    CompatibilityMinecraft 1.13
    toMinecraft 1.17
    Tags

    6 Update Logs

    2.5.0 : by RevonZev 04/16/2021 8:46:02 pmApr 16th, 2021

    LOAD MORE LOGS

    Create an account or sign in to comment.

    2
    03/22/2021 11:19 am
    Level 35 : Artisan Miner
    ButtonMenu
    ButtonMenu's Avatar
    Very cool.


    I think a feature that would be very useful is a loop over an NBT array:

    for $i in block ~ ~ ~ Items:
    data modify entity @s Item.tag.toDrop = $i
       function mypack:drop


    would compile to



    data modify storage tmpArr set from block ~ ~ ~ Items
    execute if data storage @s tmpArr[] run function mypack:z__recursive_iter


    Content of z__recursive_iter.mcfunction:

    data modify entity @s Item.tag.toDrop from storage tmpArr[0]
    function mypack:drop

    ## remove item from item list
    data remove storage @s tmpArr[0]

    ## if still items left, call this very function
    execute if data storage @s tmpArr[] run function mypack:z__recursive_iter
    1
    03/22/2021 7:14 pmhistory
    Level 62 : High Grandmaster Dragon
    RevonZev
    RevonZev's Avatar
    Can you explain? All I know is:

    for $i in block ~ ~ ~ Items:
    data modify entity @s Item.tag.toDrop = $i
       function mypack:drop

    # Compile into:
    ERROR
    data modify entity @s Item.tag.toDrop = $i
    function mypack:drop

    # Not into:
    data modify storage tmpArr set from block ~ ~ ~ Items
    execute if data storage @s tmpArr[] run function mypack:z__recursive_iter

    Do you mean a shorthand for looping NBT?
    You can also do it manually or use MCPY function.
    1
    03/23/2021 5:43 pmhistory
    Level 35 : Artisan Miner
    ButtonMenu
    ButtonMenu's Avatar
    Did you get my point? I probably could have done better at getting my idea across. Also, I think the following syntax is actually better:

    for <TARGET> <NBT path of TARGET> in <SOURCE> <NBT path of SOURCE>:
       <part that will be called for each element in SOURCE path


    So, for example:

    for entity @s Item.tag.toDrop in block ~ ~ ~ Items:
       function mypack:drop


    This would compile to two separate mcfunction files:

    - a recursive iteration mcfunction
    - the current mcfunction containing the call to just mentioned recursive mcfunction
    1
    03/22/2021 7:18 pmhistory
    Level 35 : Artisan Miner
    ButtonMenu
    ButtonMenu's Avatar
    Yeah, exactly. A shorthand for looping through NBT arrays (instead of having to write recursive calls yourself) would be awesome.


    Writing it yourself currently always requires 4 steps: 1. copy NBT array using 'data modify' to tmpArray 2. do something with the first item 3. remove first item of tmpArray 4. if still items in tmpArray, continue at 2.

    For example, in my Sorters datapack, I use recursive calls to loop over the list of items and drop all the matching ones. (The mcfunction name has "recursive" in its name, so you should fine it easily, if you want to check it out. There's also a drop_all mcfunction which is recursive and shorter.)
    1
    03/15/2021 9:39 pmhistory
    Level 24 : Expert Procrastinator
    MrPlayerYork
    MrPlayerYork's Avatar
    hey dude, making a submission for community functions. It's nothing too special but it helps with understanding what's going on.

    def compare($object,$op,$target):
    if score $object var_list $op #$target var_list:
    How to use:
    compare("var1","=","var2")
      say TRUE
    1
    03/16/2021 7:58 pmhistory
    Level 62 : High Grandmaster Dragon
    RevonZev
    RevonZev's Avatar
    What about the var_list?
    def compare($object,$objective1,$op,$target,$objective2):
    if score $object $objective1 $op #$target $objective2:
    Like this?
    1
    03/17/2021 5:52 pm
    Level 24 : Expert Procrastinator
    MrPlayerYork
    MrPlayerYork's Avatar
    that could work, ya!!
    2
    03/13/2021 3:22 amhistory
    Level 24 : Expert Procrastinator
    MrPlayerYork
    MrPlayerYork's Avatar
    Hey there, so I made a datapack a little bit ago and I was going to try recreating it with your tool. However I've run into a problem where I just want to set a value to a scoreboard variable and it keeps doing it as an operation. Here is my mcpy code:
    unless score @a[limit=1] AotdLoaded = @s AotdLoaded:
    AotdLoaded = -50
    and the output:
    execute unless score @a[limit=1] AotdLoaded = @s AotdLoaded run scoreboard players operation @s AotdLoaded = @s -50aaaand what it should be outputting:
    execute unless score @a[limit=1] AotdLoaded = @s AotdLoaded run scoreboard players set @s AotdLoaded -50
    I hope you can point out what I'm doing wrong.

    I will also post this on github.
    3
    03/13/2021 5:57 am
    Level 62 : High Grandmaster Dragon
    RevonZev
    RevonZev's Avatar
    As of v2.1.2, it is fixed.
    2
    01/27/2021 9:01 am
    Level 43 : Master Answer
    Yekc
    Yekc's Avatar
    How would you do /tellraw using this language?
    Planet Minecraft

    Website

    © 2010 - 2024
    www.planetminecraft.com

    Welcome