├── example
├── test2.planet
├── test3.planet
├── test_.planet
├── test.planet
├── wait.planet
├── health_bar.planet
└── animation.planet
├── requirements.txt
├── basic_1.20
├── data
│ ├── minecraft
│ │ └── tags
│ │ │ └── functions
│ │ │ └── load.json
│ └── basic
│ │ └── functions
│ │ ├── double
│ │ ├── convert
│ │ │ ├── 4.mcfunction
│ │ │ └── execute.mcfunction
│ │ └── execute.mcfunction
│ │ ├── float
│ │ ├── convert
│ │ │ ├── 4.mcfunction
│ │ │ └── execute.mcfunction
│ │ └── execute.mcfunction
│ │ ├── array
│ │ ├── add
│ │ │ ├── macro.mcfunction
│ │ │ └── repeat.mcfunction
│ │ ├── member
│ │ │ ├── macro.mcfunction
│ │ │ └── execute.mcfunction
│ │ ├── add.mcfunction
│ │ └── execute.mcfunction
│ │ ├── string
│ │ ├── add.mcfunction
│ │ └── execute.mcfunction
│ │ ├── int
│ │ ├── convert.mcfunction
│ │ ├── convert
│ │ │ ├── 4.mcfunction
│ │ │ └── execute.mcfunction
│ │ └── execute.mcfunction
│ │ ├── load.mcfunction
│ │ ├── get_type_score.mcfunction
│ │ ├── byte
│ │ └── execute.mcfunction
│ │ └── operation.mcfunction
└── pack.mcmeta
├── basic_1.21
├── data
│ ├── minecraft
│ │ └── tags
│ │ │ └── function
│ │ │ └── load.json
│ └── basic
│ │ └── function
│ │ ├── double
│ │ ├── convert
│ │ │ ├── 4.mcfunction
│ │ │ └── execute.mcfunction
│ │ └── execute.mcfunction
│ │ ├── float
│ │ ├── convert
│ │ │ ├── 4.mcfunction
│ │ │ └── execute.mcfunction
│ │ └── execute.mcfunction
│ │ ├── array
│ │ ├── add
│ │ │ ├── macro.mcfunction
│ │ │ └── repeat.mcfunction
│ │ ├── member
│ │ │ ├── macro.mcfunction
│ │ │ └── execute.mcfunction
│ │ ├── add.mcfunction
│ │ └── execute.mcfunction
│ │ ├── string
│ │ ├── add.mcfunction
│ │ └── execute.mcfunction
│ │ ├── int
│ │ ├── convert.mcfunction
│ │ ├── convert
│ │ │ ├── 4.mcfunction
│ │ │ └── execute.mcfunction
│ │ └── execute.mcfunction
│ │ ├── load.mcfunction
│ │ ├── get_type_score.mcfunction
│ │ ├── byte
│ │ └── execute.mcfunction
│ │ └── operation.mcfunction
└── pack.mcmeta
├── basic_1.20.zip
├── basic_1.21.zip
├── __pycache__
├── consts.cpython-312.pyc
└── logger.cpython-312.pyc
├── web
├── image
│ ├── namespace.svg
│ ├── version.svg
│ ├── file.svg
│ ├── output.svg
│ ├── global.svg
│ └── folder.svg
├── style.css
└── index.html
├── .gitignore
├── docs
└── index.html
├── rpg_planet
├── mob
│ ├── test.planet
│ ├── summon.planet
│ ├── mob.planet
│ └── health_bar.planet
├── id.planet
├── skills.planet
├── stat.planet
├── skill.planet
├── camera.planet
├── main_display.planet
└── blocks.planet
├── LICENSE.txt
├── logger.py
├── consts.py
├── README_en.md
├── log.md
├── grammer.lark
├── new_compiler.py
└── README.md
/example/test2.planet:
--------------------------------------------------------------------------------
1 | var asdf = 1
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Eel==0.18.1
2 | lark==1.2.2
3 |
--------------------------------------------------------------------------------
/example/test3.planet:
--------------------------------------------------------------------------------
1 | import test2
2 |
3 | print(test2.asdf)
--------------------------------------------------------------------------------
/basic_1.20/data/minecraft/tags/functions/load.json:
--------------------------------------------------------------------------------
1 | {"values": ["basic:load"]}
--------------------------------------------------------------------------------
/basic_1.21/data/minecraft/tags/function/load.json:
--------------------------------------------------------------------------------
1 | {"values": ["basic:load"]}
--------------------------------------------------------------------------------
/basic_1.20/pack.mcmeta:
--------------------------------------------------------------------------------
1 | { "pack": {"pack_format": 9, "description": "by 40planet"} }
--------------------------------------------------------------------------------
/basic_1.21/pack.mcmeta:
--------------------------------------------------------------------------------
1 | { "pack": {"pack_format": 9, "description": "by 40planet"} }
--------------------------------------------------------------------------------
/basic_1.20.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexmonkey05/Datapack-Compiler/HEAD/basic_1.20.zip
--------------------------------------------------------------------------------
/basic_1.21.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexmonkey05/Datapack-Compiler/HEAD/basic_1.21.zip
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/double/convert/4.mcfunction:
--------------------------------------------------------------------------------
1 | $data modify storage 40planet:value var1 set value $(type_var)d
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/float/convert/4.mcfunction:
--------------------------------------------------------------------------------
1 | $data modify storage 40planet:value var1 set value $(type_var)f
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/double/convert/4.mcfunction:
--------------------------------------------------------------------------------
1 | $data modify storage 40planet:value var1 set value $(type_var)d
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/float/convert/4.mcfunction:
--------------------------------------------------------------------------------
1 | $data modify storage 40planet:value var1 set value $(type_var)f
--------------------------------------------------------------------------------
/__pycache__/consts.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexmonkey05/Datapack-Compiler/HEAD/__pycache__/consts.cpython-312.pyc
--------------------------------------------------------------------------------
/__pycache__/logger.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexmonkey05/Datapack-Compiler/HEAD/__pycache__/logger.cpython-312.pyc
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/array/add/macro.mcfunction:
--------------------------------------------------------------------------------
1 | $data modify storage 40planet:value var1 append from storage 40planet:value var2[$(idx)]
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/array/add/macro.mcfunction:
--------------------------------------------------------------------------------
1 | $data modify storage 40planet:value var1 append from storage 40planet:value var2[$(idx)]
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/array/member/macro.mcfunction:
--------------------------------------------------------------------------------
1 | $return run data modify storage 40planet:value var1 set from storage 40planet:value var1[$(var2)]
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/array/member/macro.mcfunction:
--------------------------------------------------------------------------------
1 | $return run data modify storage 40planet:value var1 set from storage 40planet:value var1[$(var2)]
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/string/add.mcfunction:
--------------------------------------------------------------------------------
1 | $data modify storage 40planet:value return set value "$(var1)$(var2)"
2 | return run data get storage 40planet:value return
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/string/add.mcfunction:
--------------------------------------------------------------------------------
1 | $data modify storage 40planet:value return set value "$(var1)$(var2)"
2 | return run data get storage 40planet:value return
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/int/convert.mcfunction:
--------------------------------------------------------------------------------
1 | execute store result storage 40planet:value type int 1 run function basic:get_type_score
2 | function basic:convert/execute with storage 40planet:value
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/int/convert.mcfunction:
--------------------------------------------------------------------------------
1 | execute store result storage 40planet:value type int 1 run function basic:get_type_score
2 | function basic:convert/execute with storage 40planet:value
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/int/convert/4.mcfunction:
--------------------------------------------------------------------------------
1 | $scoreboard players set #temp 40planet_num $(type_var)
2 | execute store result storage 40planet:value var1 int 1 run scoreboard players get #temp 40planet_num
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/int/convert/4.mcfunction:
--------------------------------------------------------------------------------
1 | $scoreboard players set #temp 40planet_num $(type_var)
2 | execute store result storage 40planet:value var1 int 1 run scoreboard players get #temp 40planet_num
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/int/convert/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute if score #type 40planet_num matches 4 run return run function basic:int/convert/4 with storage 40planet:value
2 | execute store result storage 40planet:value var1 int 1 run data get storage 40planet:value type_var
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/int/convert/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute if score #type 40planet_num matches 4 run return run function basic:int/convert/4 with storage 40planet:value
2 | execute store result storage 40planet:value var1 int 1 run data get storage 40planet:value type_var
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/float/convert/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute if score #type 40planet_num matches 4 run return run function basic:float/convert/4 with storage 40planet:value
2 | execute store result storage 40planet:value var1 float 0.01 run data get storage 40planet:value type_var 100
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/float/convert/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute if score #type 40planet_num matches 4 run return run function basic:float/convert/4 with storage 40planet:value
2 | execute store result storage 40planet:value var1 float 0.01 run data get storage 40planet:value type_var 100
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/double/convert/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute if score #type 40planet_num matches 4 run return run function basic:double/convert/4 with storage 40planet:value
2 | execute store result storage 40planet:value var1 double 0.01 run data get storage 40planet:value type_var 100
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/double/convert/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute if score #type 40planet_num matches 4 run return run function basic:float/convert/4 with storage 40planet:value
2 | execute store result storage 40planet:value var1 double 0.001 run data get storage 40planet:value type_var 1000
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/array/add/repeat.mcfunction:
--------------------------------------------------------------------------------
1 | execute store result storage 40planet:value idx int 1 run scoreboard players add #idx 40planet_num 1
2 |
3 | function basic:array/add/macro with storage 40planet:value
4 |
5 | execute if score #idx 40planet_num < #len 40planet_num run function basic:array/add/repeat
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/array/add/repeat.mcfunction:
--------------------------------------------------------------------------------
1 | execute store result storage 40planet:value idx int 1 run scoreboard players add #idx 40planet_num 1
2 |
3 | function basic:array/add/macro with storage 40planet:value
4 |
5 | execute if score #idx 40planet_num < #len 40planet_num run function basic:array/add/repeat
--------------------------------------------------------------------------------
/web/image/namespace.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/array/add.mcfunction:
--------------------------------------------------------------------------------
1 | execute unless data storage 40planet:value var2[0] run return run data modify storage 40planet:value var1 append from storage 40planet:value var2
2 |
3 | execute store result score #len 40planet_num run data get storage 40planet:value var2
4 | scoreboard players set #idx 40planet_num -1
5 | function basic:array/add/repeat
6 | return run data get storage 40planet:value var1
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/array/add.mcfunction:
--------------------------------------------------------------------------------
1 | execute unless data storage 40planet:value var2[0] run return run data modify storage 40planet:value var1 append from storage 40planet:value var2
2 |
3 | execute store result score #len 40planet_num run data get storage 40planet:value var2
4 | scoreboard players set #idx 40planet_num -1
5 | function basic:array/add/repeat
6 | return run data get storage 40planet:value var1
--------------------------------------------------------------------------------
/example/test_.planet:
--------------------------------------------------------------------------------
1 | execute(as @a){
2 | var i = 0
3 | var inventory = get_data("entity", "@s", "Inventory")
4 | /execute store result score len num run data get entity @s Inventory
5 | var len = get_score("len", "num")
6 | while(i < len){
7 | var item = inventory[i]
8 | #if (대충 아이템 조건)
9 | var slot = inventory[i].Slot
10 | /item replace entity @s container.^slot& with <아이템>
11 | i = i + 1
12 | }
13 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | compiler.spec
2 | new_compiler.spec
3 | /build
4 | /dist
5 | /etc
6 | /pack
7 | /rpg
8 | /napolitan
9 | /temp
10 | /40planet_area
11 | /rpg_datapack
12 | /skill
13 | /minecraft_problem
14 | /health_bar
15 | /rpg 몹 모델링들
16 | /village-wildwest
17 | /village-test
18 | /rpg_mob
19 | /rpg_mob_datapack
20 | /bdengine
21 | /40planet_ani
22 | /40planet_mawang_ani
23 | /maz
24 | 40planet_ani.zip
25 | new_compiler.exe
26 | __pycache__/
27 | .venv
28 | /old_versions
29 | settings.json
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/array/member/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 |
3 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.int_arr append from storage 40planet:value var2
4 |
5 | execute unless score #type 40planet_num matches 1 run tellraw @a {"text": "Runtime Error : Index must be int type","color": "red"}
6 | execute unless score #type 40planet_num matches 1 run return fail
7 |
8 | return run function basic:array/member/macro with storage 40planet:value
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/array/member/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 |
3 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.int_arr append from storage 40planet:value var2
4 |
5 | execute unless score #type 40planet_num matches 1 run tellraw @a {"text": "Runtime Error : Index must be int type","color": "red"}
6 | execute unless score #type 40planet_num matches 1 run return fail
7 |
8 | return run function basic:array/member/macro with storage 40planet:value
--------------------------------------------------------------------------------
/web/image/version.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 | 아직 안 만들었음.
10 | 언젠간 만들거임.
11 |
12 |
13 |
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/load.mcfunction:
--------------------------------------------------------------------------------
1 | # This data pack was compiled with the 40planet's compiler.
2 | # https://github.com/alexmonkey05/Datapack-Interpreter
3 | scoreboard objectives add 40planet_num dummy
4 | scoreboard players set 100 40planet_num 100
5 | scoreboard players set #0 40planet_num 0
6 | kill 0-0-0-0-a
7 | summon text_display 0 0 0 {UUID:[I;0,0,0,10]}
8 | forceload add 0 0
9 | data remove storage 40planet:value $type_arr
10 | data modify storage 40planet:value $type_arr set value {int_arr:[1], float_arr:[1f], double_arr:[1d], string_arr:["1"], byte_arr:[1b]}
11 | data modify storage 40planet:value false set value 0b
12 | data modify storage 40planet:value true set value 1b
13 | say done!
14 |
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/load.mcfunction:
--------------------------------------------------------------------------------
1 | # This data pack was compiled with the 40planet's compiler.
2 | # https://github.com/alexmonkey05/Datapack-Interpreter
3 | scoreboard objectives add 40planet_num dummy
4 | scoreboard players set 100 40planet_num 100
5 | scoreboard players set #0 40planet_num 0
6 | kill 0-0-0-0-a
7 | summon text_display 0 0 0 {UUID:[I;0,0,0,10]}
8 | forceload add 0 0
9 | data remove storage 40planet:value $type_arr
10 | data modify storage 40planet:value $type_arr set value {int_arr:[1], float_arr:[1f], double_arr:[1d], string_arr:["1"], byte_arr:[1b]}
11 | data modify storage 40planet:value false set value 0b
12 | data modify storage 40planet:value true set value 1b
13 | say done!
14 |
--------------------------------------------------------------------------------
/example/test.planet:
--------------------------------------------------------------------------------
1 | def change_text_to_translate(){
2 | /data modify storage asdf: text set from entity @s text
3 | execute(if data entity @s text.extra){
4 | var extra = get_data("entity", "@s", "text.extra")
5 | var result = []
6 | while(extra[0]){
7 | append(result, extra[0])
8 | del(extra[0])
9 | result[-1].translate = result[-1].text
10 | del(result[-1].text)
11 | }
12 | set_data("storage", "asdf:", "text.extra", result)
13 | }
14 | /data modify storage asdf: text.translate set from storage asdf: text.text
15 | /data remove storage asdf: text.text
16 | /data modify entity @s text set from storage asdf: text
17 | }
--------------------------------------------------------------------------------
/web/image/file.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/array/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute if score #operator_type 40planet_num matches 2..11 run tellraw @a {"text": "Runtime Error : Array only can operate \"add\"","color": "red"}
2 | execute if score #operator_type 40planet_num matches 2..11 run return fail
3 |
4 | execute if score #operator_type 40planet_num matches 1 run return run function basic:array/add
5 |
6 | execute if score #operator_type 40planet_num matches 12 store result score #temp 40planet_num run data get storage 40planet:value var1
7 | execute if score #operator_type 40planet_num matches 12 run return run execute unless score #temp 40planet_num matches 0
8 |
9 | execute if score #operator_type 40planet_num matches 13 run return run function basic:array/member/execute
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/array/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute if score #operator_type 40planet_num matches 2..11 run tellraw @a {"text": "Runtime Error : Array only can operate \"add\"","color": "red"}
2 | execute if score #operator_type 40planet_num matches 2..11 run return fail
3 |
4 | execute if score #operator_type 40planet_num matches 1 run return run function basic:array/add
5 |
6 | execute if score #operator_type 40planet_num matches 12 store result score #temp 40planet_num run data get storage 40planet:value var1
7 | execute if score #operator_type 40planet_num matches 12 run return run execute unless score #temp 40planet_num matches 0
8 |
9 | execute if score #operator_type 40planet_num matches 13 run return run function basic:array/member/execute
--------------------------------------------------------------------------------
/rpg_planet/mob/test.planet:
--------------------------------------------------------------------------------
1 | def death(){
2 | /execute on passengers run data modify entity @s text set value '{"text":"죽음"}'
3 | /execute on passengers run ride @s dismount
4 | /tp @s ~ ~1000 ~
5 | /kill @s
6 | }
7 |
8 | def attack(){
9 | /scoreboard players set @s 40planet_num 10
10 | /execute on passengers run data modify entity @s text set value '{"text":"공격"}'
11 | }
12 |
13 | def test_tick(){
14 | execute(if score "@s" "40planet_is_death" matches 1){
15 | death()
16 | return 0
17 | }
18 | /execute if score @s 40planet_num matches 0.. run scoreboard players remove @s 40planet_num 1
19 | execute(if score "@s" "40planet_num" matches 0){
20 | /execute on passengers run data modify entity @s text set value '{"text":"기본"}'
21 | }
22 | }
--------------------------------------------------------------------------------
/web/image/output.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/web/image/global.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 BASTOIN
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/web/image/folder.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rpg_planet/id.planet:
--------------------------------------------------------------------------------
1 | /scoreboard objectives add 40planet_id dummy
2 |
3 | def set_id(){
4 |
5 | var uuid = get_data("entity", "@s", "UUID")
6 | /scoreboard players set is_uuid_exist 40planet_num 0
7 | /execute if data storage 40planet:id player."^uuid&".id run scoreboard players set is_uuid_exist 40planet_num 1
8 | # uuid가 있을 때
9 | /execute if score is_uuid_exist 40planet_num matches 1 store result score @s 40planet_id run data get storage 40planet:id player."^uuid&".id
10 | # uuid가 없을 때
11 | execute(if score "is_uuid_exist" "40planet_num" matches 0){
12 | /execute store result score @s 40planet_id run scoreboard players add $first 40planet_id 1
13 | /execute store result storage 40planet:id player."^uuid&".id int 1 run scoreboard players get $first 40planet_id
14 | }
15 | return get_score("@s", "40planet_id")
16 | }
17 |
18 | def tick(){
19 | /execute as @a unless score @s 40planet_id = @s 40planet_id run function __namespace__:set_id
20 |
21 | # if(is_module()){ return 0 }
22 | }
23 |
24 | def get_id(){
25 | return get_score("@s", "40planet_id")
26 | }
27 |
28 |
29 | /execute unless score $first 40planet_id = $first 40planet_id run scoreboard players set $first 40planet_id -2147483647
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/string/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute unless score #var1_type 40planet_num matches 4 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
2 | execute unless score #var1_type 40planet_num matches 4 run return fail
3 |
4 | execute if score #operator_type 40planet_num matches 1 run return run function basic:string/add with storage 40planet:value
5 | execute if score #operator_type 40planet_num matches 2..5 run tellraw @a {"text": "Runtime Error : String only can operate \"add\"","color": "red"}
6 | execute if score #operator_type 40planet_num matches 2..5 run return fail
7 | execute if score #operator_type 40planet_num matches 6..7 store success score #var1 40planet_num run data modify storage 40planet:value var1 set from storage 40planet:value var2
8 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num matches 0
9 | execute if score #operator_type 40planet_num matches 7 run return run execute if score #var1 40planet_num matches 1
10 | execute if score #operator_type 40planet_num matches 8..11 run tellraw @a {"text": "Runtime Error : String only can operate \"add\"","color": "red"}
11 | execute if score #operator_type 40planet_num matches 8..11 run return fail
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/string/execute.mcfunction:
--------------------------------------------------------------------------------
1 | execute unless score #var1_type 40planet_num matches 4 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
2 | execute unless score #var1_type 40planet_num matches 4 run return fail
3 |
4 | execute if score #operator_type 40planet_num matches 1 run return run function basic:string/add with storage 40planet:value
5 | execute if score #operator_type 40planet_num matches 2..5 run tellraw @a {"text": "Runtime Error : String only can operate \"add\"","color": "red"}
6 | execute if score #operator_type 40planet_num matches 2..5 run return fail
7 | execute if score #operator_type 40planet_num matches 6..7 store success score #var1 40planet_num run data modify storage 40planet:value var1 set from storage 40planet:value var2
8 | execute if score #operator_type 40planet_num matches 6 store result storage 40planet:value var1 int 1 run return run execute if score #var1 40planet_num matches 0
9 | execute if score #operator_type 40planet_num matches 7 store result storage 40planet:value var1 int 1 run return run execute if score #var1 40planet_num matches 1
10 | execute if score #operator_type 40planet_num matches 8..11 run tellraw @a {"text": "Runtime Error : String only can operate \"add\"","color": "red"}
11 | execute if score #operator_type 40planet_num matches 8..11 run return fail
--------------------------------------------------------------------------------
/example/wait.planet:
--------------------------------------------------------------------------------
1 |
2 |
3 | var schedule = []
4 |
5 | /scoreboard objectives add 40planet_num dummy
6 |
7 | def wait_tick(){
8 | var schedule_copy = schedule
9 | schedule = []
10 | while(schedule_copy[0]){
11 | var function_fun = schedule_copy[0].function
12 | var condition_fun = schedule_copy[0].condition
13 | /scoreboard players set #is_wait_end 40planet_num 0
14 | /$execute store result score #is_wait_end 40planet_num run $(condition_fun)
15 | execute(if score "#is_wait_end" 40planet_num matches 1..){
16 | /$$(function_fun)
17 | }
18 | execute(if score "#is_wait_end" 40planet_num matches ..0){
19 | append(schedule, schedule_copy[0])
20 | }
21 | del(schedule_copy[0])
22 | }
23 | if(schedule[0]){
24 | /schedule function __namespace__:wait_tick 1t
25 | }
26 | }
27 |
28 | # condition 될 때까지 기다리기
29 | def wait(var condition_param, var function_param){
30 | # condition = condition_param
31 | # function = function_param
32 | append(schedule, {
33 | condition: condition_param,
34 | function: function_param
35 | })
36 |
37 | /schedule function __namespace__:wait_tick 1t
38 | }
39 |
40 | def test(){
41 | /scoreboard players set wait_test 40planet_num 0
42 | wait("execute if score wait_test 40planet_num matches 1", "say wait 끝남")
43 | }
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/get_type_score.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.int_arr append from storage 40planet:value type_var
3 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.int_arr[1]
4 | execute if score #type 40planet_num matches 1 run return 1
5 |
6 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.float_arr append from storage 40planet:value type_var
7 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.float_arr[1]
8 | execute if score #type 40planet_num matches 1 run return 2
9 |
10 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.byte_arr append from storage 40planet:value type_var
11 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.byte_arr[1]
12 | execute if score #type 40planet_num matches 1 run return 5
13 |
14 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.double_arr append from storage 40planet:value type_var
15 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.double_arr[1]
16 | execute if score #type 40planet_num matches 1 run return 3
17 |
18 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.string_arr append from storage 40planet:value type_var
19 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.string_arr[1]
20 | execute if score #type 40planet_num matches 1 run return 4
21 |
22 | return 0
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/get_type_score.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.int_arr append from storage 40planet:value type_var
3 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.int_arr[1]
4 | execute if score #type 40planet_num matches 1 run return 1
5 |
6 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.float_arr append from storage 40planet:value type_var
7 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.float_arr[1]
8 | execute if score #type 40planet_num matches 1 run return 2
9 |
10 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.byte_arr append from storage 40planet:value type_var
11 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.byte_arr[1]
12 | execute if score #type 40planet_num matches 1 run return 5
13 |
14 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.double_arr append from storage 40planet:value type_var
15 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.double_arr[1]
16 | execute if score #type 40planet_num matches 1 run return 3
17 |
18 | execute store success score #type 40planet_num run data modify storage 40planet:value $type_arr.string_arr append from storage 40planet:value type_var
19 | execute if score #type 40planet_num matches 1 run data remove storage 40planet:value $type_arr.string_arr[1]
20 | execute if score #type 40planet_num matches 1 run return 4
21 |
22 | return 0
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/byte/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute unless score #var1_type 40planet_num matches 5 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
3 | execute unless score #var1_type 40planet_num matches 5 run return fail
4 |
5 | execute store result score #var1 40planet_num run data get storage 40planet:value var1
6 | execute store result score #var2 40planet_num run data get storage 40planet:value var2
7 |
8 | execute if score #operator_type 40planet_num matches 1 run return run scoreboard players operation #var1 40planet_num += #var2 40planet_num
9 | execute if score #operator_type 40planet_num matches 2 run return run scoreboard players operation #var1 40planet_num -= #var2 40planet_num
10 | execute if score #operator_type 40planet_num matches 3 run return run scoreboard players operation #var1 40planet_num *= #var2 40planet_num
11 | execute if score #operator_type 40planet_num matches 4 run return run scoreboard players operation #var1 40planet_num /= #var2 40planet_num
12 | execute if score #operator_type 40planet_num matches 5 run return run scoreboard players operation #var1 40planet_num %= #var2 40planet_num
13 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num = #var2 40planet_num
14 | execute if score #operator_type 40planet_num matches 7 run return run execute unless score #var1 40planet_num = #var2 40planet_num
15 | execute if score #operator_type 40planet_num matches 8 run return run execute if score #var1 40planet_num >= #var2 40planet_num
16 | execute if score #operator_type 40planet_num matches 9 run return run execute if score #var1 40planet_num > #var2 40planet_num
17 | execute if score #operator_type 40planet_num matches 10 run return run execute if score #var1 40planet_num <= #var2 40planet_num
18 | execute if score #operator_type 40planet_num matches 11 run return run execute if score #var1 40planet_num < #var2 40planet_num
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/byte/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute unless score #var1_type 40planet_num matches 5 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
3 | execute unless score #var1_type 40planet_num matches 5 run return fail
4 |
5 | execute store result score #var1 40planet_num run data get storage 40planet:value var1
6 | execute store result score #var2 40planet_num run data get storage 40planet:value var2
7 |
8 | execute if score #operator_type 40planet_num matches 1 run return run scoreboard players operation #var1 40planet_num += #var2 40planet_num
9 | execute if score #operator_type 40planet_num matches 2 run return run scoreboard players operation #var1 40planet_num -= #var2 40planet_num
10 | execute if score #operator_type 40planet_num matches 3 run return run scoreboard players operation #var1 40planet_num *= #var2 40planet_num
11 | execute if score #operator_type 40planet_num matches 4 run return run scoreboard players operation #var1 40planet_num /= #var2 40planet_num
12 | execute if score #operator_type 40planet_num matches 5 run return run scoreboard players operation #var1 40planet_num %= #var2 40planet_num
13 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num = #var2 40planet_num
14 | execute if score #operator_type 40planet_num matches 7 run return run execute unless score #var1 40planet_num = #var2 40planet_num
15 | execute if score #operator_type 40planet_num matches 8 run return run execute if score #var1 40planet_num >= #var2 40planet_num
16 | execute if score #operator_type 40planet_num matches 9 run return run execute if score #var1 40planet_num > #var2 40planet_num
17 | execute if score #operator_type 40planet_num matches 10 run return run execute if score #var1 40planet_num <= #var2 40planet_num
18 | execute if score #operator_type 40planet_num matches 11 run return run execute if score #var1 40planet_num < #var2 40planet_num
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/int/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute unless score #var1_type 40planet_num matches 1..3 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
3 | execute unless score #var1_type 40planet_num matches 1..3 run return fail
4 |
5 | execute store result score #var1 40planet_num run data get storage 40planet:value var1
6 | execute store result score #var2 40planet_num run data get storage 40planet:value var2
7 |
8 | execute if score #operator_type 40planet_num matches 1 run return run scoreboard players operation #var1 40planet_num += #var2 40planet_num
9 | execute if score #operator_type 40planet_num matches 2 run return run scoreboard players operation #var1 40planet_num -= #var2 40planet_num
10 | execute if score #operator_type 40planet_num matches 3 run return run scoreboard players operation #var1 40planet_num *= #var2 40planet_num
11 | execute if score #operator_type 40planet_num matches 4 run return run scoreboard players operation #var1 40planet_num /= #var2 40planet_num
12 | execute if score #operator_type 40planet_num matches 5 run return run scoreboard players operation #var1 40planet_num %= #var2 40planet_num
13 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num = #var2 40planet_num
14 | execute if score #operator_type 40planet_num matches 7 run return run execute unless score #var1 40planet_num = #var2 40planet_num
15 | execute if score #operator_type 40planet_num matches 8 run return run execute if score #var1 40planet_num >= #var2 40planet_num
16 | execute if score #operator_type 40planet_num matches 9 run return run execute if score #var1 40planet_num > #var2 40planet_num
17 | execute if score #operator_type 40planet_num matches 10 run return run execute if score #var1 40planet_num <= #var2 40planet_num
18 | execute if score #operator_type 40planet_num matches 11 run return run execute if score #var1 40planet_num < #var2 40planet_num
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/int/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute unless score #var1_type 40planet_num matches 1..3 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
3 | execute unless score #var1_type 40planet_num matches 1..3 run return fail
4 |
5 | execute store result score #var1 40planet_num run data get storage 40planet:value var1
6 | execute store result score #var2 40planet_num run data get storage 40planet:value var2
7 |
8 | execute if score #operator_type 40planet_num matches 1 run return run scoreboard players operation #var1 40planet_num += #var2 40planet_num
9 | execute if score #operator_type 40planet_num matches 2 run return run scoreboard players operation #var1 40planet_num -= #var2 40planet_num
10 | execute if score #operator_type 40planet_num matches 3 run return run scoreboard players operation #var1 40planet_num *= #var2 40planet_num
11 | execute if score #operator_type 40planet_num matches 4 run return run scoreboard players operation #var1 40planet_num /= #var2 40planet_num
12 | execute if score #operator_type 40planet_num matches 5 run return run scoreboard players operation #var1 40planet_num %= #var2 40planet_num
13 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num = #var2 40planet_num
14 | execute if score #operator_type 40planet_num matches 7 run return run execute unless score #var1 40planet_num = #var2 40planet_num
15 | execute if score #operator_type 40planet_num matches 8 run return run execute if score #var1 40planet_num >= #var2 40planet_num
16 | execute if score #operator_type 40planet_num matches 9 run return run execute if score #var1 40planet_num > #var2 40planet_num
17 | execute if score #operator_type 40planet_num matches 10 run return run execute if score #var1 40planet_num <= #var2 40planet_num
18 | execute if score #operator_type 40planet_num matches 11 run return run execute if score #var1 40planet_num < #var2 40planet_num
--------------------------------------------------------------------------------
/rpg_planet/mob/summon.planet:
--------------------------------------------------------------------------------
1 |
2 | def set_basic(){
3 | /effect give @s invisibility infinite 0 true
4 | /attribute @s generic.max_health base set 1000
5 | /data modify entity @s Health set value 1000f
6 | /effect give @s resistance infinite 3 true
7 | /tag @s add 40planet_rpg_mob
8 | # 나중에 1.21.2 나오면 item_model 공기로 바꿔서 안 보이게 하기
9 | /item replace entity @s weapon with stone_button[enchantments={"rpg_mob:detect_attack":1}]
10 | }
11 |
12 | def orange_mushroom(){
13 | execute(summon slime){
14 | /data merge entity @s {DeathLootTable:"mob:entities/orange_mushroom",Tags:["mob","orange_mushroom","same_rotation"],Size:0,Health:1000f,Passengers:[{Tags:["mob_display"],id:"item_display",item:{id:"carrot_on_a_stick",Count:1b,components:{"minecraft:custom_model_data":1000001}}}]}
15 | set_basic()
16 | /scoreboard players set @s mob_health -10
17 | }
18 | }
19 |
20 | def blue_mushroom(){
21 | execute(summon slime){
22 | /data merge entity @s {DeathLootTable:"mob:entities/orange_mushroom",Tags:["mob","orange_mushroom","same_rotation"],Size:0,Health:1000f,Passengers:[{Tags:["mob_display"],id:"item_display",item:{id:"carrot_on_a_stick",Count:1b,components:{"minecraft:custom_model_data":1000001}}}]}
23 | set_basic()
24 | /scoreboard players set @s mob_health -10
25 | }
26 | }
27 |
28 | def test(){
29 | execute(summon husk){
30 | /summon text_display ~ ~ ~ {Tags:["unset","40planet_mob_display"],text:'{"text":"기본"}',billboard:"vertical",transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[2f,2f,2f],translation:[0f,.5f,0f]}}
31 | /ride @n[distance=..0.01,tag=unset] mount @s
32 | /execute on passengers run tag @s remove unset
33 | set_basic()
34 | /effect clear @s invisibility
35 | # 죽음 애니메이션 길이 1초로 설정
36 | /scoreboard players set @s 40planet_death_animation_len 20
37 | /data modify entity @s DeathLootTable set value ""
38 | /tag @s add 40planet_test
39 | # 체력 20으로 설정
40 | /scoreboard players set @s 40planet_rpg_health 200
41 | }
42 | }
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/float/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute unless score #var1_type 40planet_num matches 1..3 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
3 | execute unless score #var1_type 40planet_num matches 1..3 run return fail
4 |
5 | execute store result score #var1 40planet_num run data get storage 40planet:value var1 100
6 | execute store result score #var2 40planet_num run data get storage 40planet:value var2 100
7 |
8 | execute if score #operator_type 40planet_num matches 1 run return run scoreboard players operation #var1 40planet_num += #var2 40planet_num
9 | execute if score #operator_type 40planet_num matches 2 run return run scoreboard players operation #var1 40planet_num -= #var2 40planet_num
10 | execute if score #operator_type 40planet_num matches 3 run scoreboard players operation #var1 40planet_num *= #var2 40planet_num
11 | execute if score #operator_type 40planet_num matches 3 run return run scoreboard players operation #var1 40planet_num /= 100 40planet_num
12 | execute if score #operator_type 40planet_num matches 4 run scoreboard players operation #var1 40planet_num *= 100 40planet_num
13 | execute if score #operator_type 40planet_num matches 4 run return run scoreboard players operation #var1 40planet_num /= #var2 40planet_num
14 | execute if score #operator_type 40planet_num matches 5 run return run scoreboard players operation #var1 40planet_num %= #var2 40planet_num
15 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num = #var2 40planet_num
16 | execute if score #operator_type 40planet_num matches 7 run return run execute unless score #var1 40planet_num = #var2 40planet_num
17 | execute if score #operator_type 40planet_num matches 8 run return run execute if score #var1 40planet_num >= #var2 40planet_num
18 | execute if score #operator_type 40planet_num matches 9 run return run execute if score #var1 40planet_num > #var2 40planet_num
19 | execute if score #operator_type 40planet_num matches 10 run return run execute if score #var1 40planet_num <= #var2 40planet_num
20 | execute if score #operator_type 40planet_num matches 11 run return run execute if score #var1 40planet_num < #var2 40planet_num
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/double/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute unless score #var1_type 40planet_num matches 1..3 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
3 | execute unless score #var1_type 40planet_num matches 1..3 run return fail
4 |
5 | execute store result score #var1 40planet_num run data get storage 40planet:value var1 100
6 | execute store result score #var2 40planet_num run data get storage 40planet:value var2 100
7 |
8 | execute if score #operator_type 40planet_num matches 1 run return run scoreboard players operation #var1 40planet_num += #var2 40planet_num
9 | execute if score #operator_type 40planet_num matches 2 run return run scoreboard players operation #var1 40planet_num -= #var2 40planet_num
10 | execute if score #operator_type 40planet_num matches 3 run scoreboard players operation #var1 40planet_num *= #var2 40planet_num
11 | execute if score #operator_type 40planet_num matches 3 run return run scoreboard players operation #var1 40planet_num /= 100 40planet_num
12 | execute if score #operator_type 40planet_num matches 4 run scoreboard players operation #var1 40planet_num *= 100 40planet_num
13 | execute if score #operator_type 40planet_num matches 4 run return run scoreboard players operation #var1 40planet_num /= #var2 40planet_num
14 | execute if score #operator_type 40planet_num matches 5 run return run scoreboard players operation #var1 40planet_num %= #var2 40planet_num
15 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num = #var2 40planet_num
16 | execute if score #operator_type 40planet_num matches 7 run return run execute unless score #var1 40planet_num = #var2 40planet_num
17 | execute if score #operator_type 40planet_num matches 8 run return run execute if score #var1 40planet_num >= #var2 40planet_num
18 | execute if score #operator_type 40planet_num matches 9 run return run execute if score #var1 40planet_num > #var2 40planet_num
19 | execute if score #operator_type 40planet_num matches 10 run return run execute if score #var1 40planet_num <= #var2 40planet_num
20 | execute if score #operator_type 40planet_num matches 11 run return run execute if score #var1 40planet_num < #var2 40planet_num
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/float/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute unless score #var1_type 40planet_num matches 1..3 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
3 | execute unless score #var1_type 40planet_num matches 1..3 run return fail
4 |
5 | execute store result score #var1 40planet_num run data get storage 40planet:value var1 100
6 | execute store result score #var2 40planet_num run data get storage 40planet:value var2 100
7 |
8 | execute if score #operator_type 40planet_num matches 1 run return run scoreboard players operation #var1 40planet_num += #var2 40planet_num
9 | execute if score #operator_type 40planet_num matches 2 run return run scoreboard players operation #var1 40planet_num -= #var2 40planet_num
10 | execute if score #operator_type 40planet_num matches 3 run scoreboard players operation #var1 40planet_num *= #var2 40planet_num
11 | execute if score #operator_type 40planet_num matches 3 run return run scoreboard players operation #var1 40planet_num /= 100 40planet_num
12 | execute if score #operator_type 40planet_num matches 4 run scoreboard players operation #var1 40planet_num *= 100 40planet_num
13 | execute if score #operator_type 40planet_num matches 4 run return run scoreboard players operation #var1 40planet_num /= #var2 40planet_num
14 | execute if score #operator_type 40planet_num matches 5 run return run scoreboard players operation #var1 40planet_num %= #var2 40planet_num
15 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num = #var2 40planet_num
16 | execute if score #operator_type 40planet_num matches 7 run return run execute unless score #var1 40planet_num = #var2 40planet_num
17 | execute if score #operator_type 40planet_num matches 8 run return run execute if score #var1 40planet_num >= #var2 40planet_num
18 | execute if score #operator_type 40planet_num matches 9 run return run execute if score #var1 40planet_num > #var2 40planet_num
19 | execute if score #operator_type 40planet_num matches 10 run return run execute if score #var1 40planet_num <= #var2 40planet_num
20 | execute if score #operator_type 40planet_num matches 11 run return run execute if score #var1 40planet_num < #var2 40planet_num
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/double/execute.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute unless score #var1_type 40planet_num matches 1..3 run tellraw @a {"text": "Runtime Error : Operands must be of the same data type","color": "red"}
3 | execute unless score #var1_type 40planet_num matches 1..3 run return fail
4 |
5 | execute store result score #var1 40planet_num run data get storage 40planet:value var1 100
6 | execute store result score #var2 40planet_num run data get storage 40planet:value var2 100
7 |
8 | execute if score #operator_type 40planet_num matches 1 run return run scoreboard players operation #var1 40planet_num += #var2 40planet_num
9 | execute if score #operator_type 40planet_num matches 2 run return run scoreboard players operation #var1 40planet_num -= #var2 40planet_num
10 | execute if score #operator_type 40planet_num matches 3 run scoreboard players operation #var1 40planet_num *= #var2 40planet_num
11 | execute if score #operator_type 40planet_num matches 3 run return run scoreboard players operation #var1 40planet_num /= 100 40planet_num
12 | execute if score #operator_type 40planet_num matches 4 run scoreboard players operation #var1 40planet_num *= 100 40planet_num
13 | execute if score #operator_type 40planet_num matches 4 run return run scoreboard players operation #var1 40planet_num /= #var2 40planet_num
14 | execute if score #operator_type 40planet_num matches 5 run return run scoreboard players operation #var1 40planet_num %= #var2 40planet_num
15 | execute if score #operator_type 40planet_num matches 6 run return run execute if score #var1 40planet_num = #var2 40planet_num
16 | execute if score #operator_type 40planet_num matches 7 run return run execute unless score #var1 40planet_num = #var2 40planet_num
17 | execute if score #operator_type 40planet_num matches 8 run return run execute if score #var1 40planet_num >= #var2 40planet_num
18 | execute if score #operator_type 40planet_num matches 9 run return run execute if score #var1 40planet_num > #var2 40planet_num
19 | execute if score #operator_type 40planet_num matches 10 run return run execute if score #var1 40planet_num <= #var2 40planet_num
20 | execute if score #operator_type 40planet_num matches 11 run return run execute if score #var1 40planet_num < #var2 40planet_num
--------------------------------------------------------------------------------
/basic_1.20/data/basic/functions/operation.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute if data storage 40planet:value var1[0] run return run function basic:array/execute
3 | execute unless data storage 40planet:value var1[0] if data storage 40planet:value var2[0] run tellraw @a {"text": "Runtime Error : Array can only be operated with array","color": "red"}
4 | execute unless data storage 40planet:value var1[0] if data storage 40planet:value var2[0] run return fail
5 |
6 | data modify storage 40planet:value type_var set from storage 40planet:value var1
7 | execute store result score #var1_type 40planet_num run function basic:get_type_score
8 |
9 | # execute if score #var1_type 40planet_num matches 0 if score #operator_type 40planet_num matches 14 run return run function
10 |
11 | execute if score #var1_type 40planet_num matches 0 run tellraw @a {"text": "Runtime Error : nbt type can not be operated","color": "red"}
12 | execute if score #var1_type 40planet_num matches 0 run return fail
13 |
14 | execute if score #operator_type 40planet_num matches 12 store result score #var1 40planet_num run data get storage 40planet:value var1
15 | execute if score #operator_type 40planet_num matches 12 run return run execute unless score #var1 40planet_num matches 0
16 |
17 | data modify storage 40planet:value type_var set from storage 40planet:value var2
18 | execute store result score #var2_type 40planet_num run function basic:get_type_score
19 | execute if score #var2_type 40planet_num matches 0 run tellraw @a {"text": "Runtime Error : nbt type can not be operated","color": "red"}
20 | execute if score #var2_type 40planet_num matches 0 run return fail
21 |
22 | execute if score #var2_type 40planet_num matches 1 store result storage 40planet:value var1 int 1 run return run function basic:int/execute
23 | execute if score #var2_type 40planet_num matches 2 store result storage 40planet:value var1 float 0.01 run return run function basic:float/execute
24 | execute if score #var2_type 40planet_num matches 3 store result storage 40planet:value var1 double 0.01 run return run function basic:double/execute
25 | execute if score #var2_type 40planet_num matches 4 run return run function basic:string/execute
26 | execute if score #var2_type 40planet_num matches 5 store result storage 40planet:value var1 byte 1 run return run function basic:byte/execute
27 |
28 | # execute if score #var1_type 40planet_num matches 2..3 run return run data get storage 40planet:value var1 100
29 | # return run data get storage 40planet:value var1
--------------------------------------------------------------------------------
/basic_1.21/data/basic/function/operation.mcfunction:
--------------------------------------------------------------------------------
1 |
2 | execute if data storage 40planet:value var1[0] run return run function basic:array/execute
3 | execute unless data storage 40planet:value var1[0] if data storage 40planet:value var2[0] run tellraw @a {"text": "Runtime Error : Array can only be operated with array","color": "red"}
4 | execute unless data storage 40planet:value var1[0] if data storage 40planet:value var2[0] run return fail
5 |
6 | data modify storage 40planet:value type_var set from storage 40planet:value var1
7 | execute store result score #var1_type 40planet_num run function basic:get_type_score
8 |
9 | # execute if score #var1_type 40planet_num matches 0 if score #operator_type 40planet_num matches 14 run return run function
10 |
11 | execute if score #var1_type 40planet_num matches 0 run tellraw @a {"text": "Runtime Error : nbt type can not be operated","color": "red"}
12 | execute if score #var1_type 40planet_num matches 0 run return fail
13 |
14 | execute if score #operator_type 40planet_num matches 12 store result score #var1 40planet_num run data get storage 40planet:value var1
15 | execute if score #operator_type 40planet_num matches 12 run return run execute unless score #var1 40planet_num matches 0
16 |
17 | data modify storage 40planet:value type_var set from storage 40planet:value var2
18 | execute store result score #var2_type 40planet_num run function basic:get_type_score
19 | execute if score #var2_type 40planet_num matches 0 run tellraw @a {"text": "Runtime Error : nbt type can not be operated","color": "red"}
20 | execute if score #var2_type 40planet_num matches 0 run return fail
21 |
22 | execute if score #var2_type 40planet_num matches 1 store result storage 40planet:value var1 int 1 run return run function basic:int/execute
23 | execute if score #var2_type 40planet_num matches 2 store result storage 40planet:value var1 float 0.01 run return run function basic:float/execute
24 | execute if score #var2_type 40planet_num matches 3 store result storage 40planet:value var1 double 0.01 run return run function basic:double/execute
25 | execute if score #var2_type 40planet_num matches 4 run return run function basic:string/execute
26 | execute if score #var2_type 40planet_num matches 5 store result storage 40planet:value var1 byte 1 run return run function basic:byte/execute
27 |
28 | # execute if score #var1_type 40planet_num matches 2..3 run return run data get storage 40planet:value var1 100
29 | # return run data get storage 40planet:value var1
--------------------------------------------------------------------------------
/logger.py:
--------------------------------------------------------------------------------
1 |
2 | #######################################
3 | # LOGGER
4 | #######################################
5 |
6 | import time
7 |
8 | # 수가 더 클 수록 더 많이 표시되는 것
9 | LOGLEVEL = {
10 | "DEBUG": 256,
11 | "INFO": 128,
12 | "WARNING": 64,
13 | "ERROR": 32,
14 | "CRITICAL": 16,
15 | "FATAL": 8,
16 | "LOG": 4,
17 | }
18 |
19 | # verboseLevel = LOGLEVEL["DEBUG"]
20 |
21 | class L:
22 | def __init__(self): self.verboseLevel = LOGLEVEL["INFO"]
23 | def prCyan(self, skk): return "\033[96m{}\033[00m".format(skk)
24 | def prYello(self, skk): return "\033[93m{}\033[00m".format(skk)
25 | def prRed(self, skk): return "\033[91m{}\033[00m".format(skk)
26 | def prGreen(self, skk): return "\033[92m{}\033[00m".format(skk)
27 | def prPurple(self, skk): return "\033[95m{}\033[00m".format(skk)
28 | def prGray(self, skk): return "\033[90m{}\033[00m".format(skk)
29 |
30 | def getTimeSTR(self):
31 | return time.strftime("%H:%M:%S", time.localtime())
32 |
33 | def print(self, scope: str, message, level: int = LOGLEVEL["DEBUG"]):
34 | if level > self.verboseLevel:
35 | return
36 | inf = self.prCyan("[INFO ]")
37 | if level == LOGLEVEL["ERROR"]:
38 | inf = self.prRed("[ERROR ]")
39 | if level == LOGLEVEL["WARNING"]:
40 | inf = self.prYello("[WARNING ]")
41 | if level == LOGLEVEL["LOG"]:
42 | inf = self.prGreen("[LOG ]")
43 | if level == LOGLEVEL["CRITICAL"]:
44 | inf = self.prPurple("[CRITICAL]")
45 | if level == LOGLEVEL["DEBUG"]:
46 | inf = self.prGray("[DEBUG ]")
47 |
48 | yl = self.prYello(f"[{str.ljust(scope, 20)}]")
49 | if(message == ""):
50 | print(f"[{self.getTimeSTR()}] {inf} {self.prYello("[global ]")} {scope}")
51 | else:
52 | print(f"[{self.getTimeSTR()}] {inf} {yl} {message}")
53 |
54 | def debug(self, scope: str, message = ""):
55 | self.print(scope, message, level=LOGLEVEL["DEBUG"])
56 | def info(self, scope: str, message = ""):
57 | self.print(scope, message, level=LOGLEVEL["INFO"])
58 | def warning(self, scope: str, message = ""):
59 | self.print(scope, message, level=LOGLEVEL["WARNING"])
60 | def error(self, scope: str, message = ""):
61 | self.print(scope, message, level=LOGLEVEL["ERROR"])
62 | def critical(self, scope: str, message = ""):
63 | self.print(scope, message, level=LOGLEVEL["CRITICAL"])
64 | def log(self, scope: str, message = ""):
65 | self.print(scope, message, level=LOGLEVEL["LOG"])
66 |
67 | def fit(self, stri: str, length: int):
68 | stri = str(stri)
69 | if(len(stri) <= length):
70 | return str.ljust(stri, length)
71 | else:
72 | strlen = len(stri)
73 | return "..." + stri[strlen - length + 3:]
--------------------------------------------------------------------------------
/rpg_planet/mob/mob.planet:
--------------------------------------------------------------------------------
1 | import health_bar
2 | import test
3 | import summon
4 |
5 | /scoreboard objectives add 40planet_reduced_health dummy
6 | /scoreboard objectives add 40planet_rpg_health dummy
7 | /scoreboard objectives add 40planet_is_death dummy
8 | /scoreboard objectives add 40planet_death_animation_len dummy
9 | /scoreboard players set -5 40planet_num -5
10 |
11 |
12 | def detect_death(){
13 | # 체력 가져오기
14 | /execute store result score @s 40planet_reduced_health run data get entity @s Health 10
15 | /scoreboard players remove @s 40planet_reduced_health 10000
16 | /scoreboard players operation @s 40planet_reduced_health *= -5 40planet_num
17 | # 죽음 감지
18 | /execute if score @s 40planet_reduced_health >= @s 40planet_rpg_health run scoreboard players set @s 40planet_is_death 1
19 | # 죽음 애니메이션 길이 설정
20 | /scoreboard players operation temp 40planet_num = @s 40planet_death_animation_len
21 | /execute on passengers run scoreboard players operation @s 40planet_death_animation_len = temp 40planet_num
22 | }
23 |
24 | def mob_tick(){
25 | # 죽음 감지
26 | detect_death()
27 | # 각 몬스터에게 맞는 tick 함수 실행
28 | execute(if entity @s[tag=40planet_test]){ test.test_tick() }
29 |
30 | }
31 |
32 | def mob_attack(){
33 | /say attack
34 | # 각 몬스터에게 맞는 attack 함수 실행
35 | execute(if entity @s[tag=40planet_test]){ test.attack() }
36 |
37 | }
38 |
39 | # 엘리트 몹이 될 가능성이 있는 몹 타입 태그
40 | var mob_type = "#minecraft:undead"
41 |
42 | def tick(){
43 | execute(as @e[type=!player]){
44 | # 엘리트몹 설정
45 | /scoreboard players set is_mob 40planet_num 0
46 | /execute if entity @s[tag=,type=^mob_type&] run scoreboard players set is_mob 40planet_num 1
47 | execute(if score "is_mob" "40planet_num" matches 1){
48 | /execute store result score temp 40planet_num run random value 1..1000
49 | execute(if score "temp" "40planet_num" matches ..100){
50 | /tag @s add elite_mob
51 | /attribute @s minecraft:generic.scale base set 1.5
52 | /execute store result score temp 40planet_num run random value 1..4
53 | var loot_table_num = get_score("temp", "40planet_num")
54 | /data modify entity @s DeathLootTable set value "rpg:elite_mob^loot_table_num&"
55 | /effect give @s resistance infinite 0 true
56 | }
57 | /tag @s add at_e
58 | }
59 | execute(if entity @s[tag=40planet_rpg_mob]){
60 | mob_tick()
61 | health_bar.health_bar_tick()
62 | }
63 | execute(if entity @s[tag=40planet_mob_display] unless predicate rpg_mob:vehicle){
64 | /scoreboard players remove @s 40planet_death_animation_len 1
65 | /execute if score @s 40planet_death_animation_len matches ..0 run kill @s
66 | }
67 | execute(as @s[tag=health_bar_display] unless predicate rpg_mob:vehicle){
68 | /execute on passengers run kill @s
69 | /kill @s
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/rpg_planet/skills.planet:
--------------------------------------------------------------------------------
1 | /scoreboard objectives add dash_cool dummy
2 |
3 | def dash(){
4 |
5 |
6 | # "f35ac18d-c25b-4091-8e16-83071bd82518" 아이템 디티티
7 | # "4aa462f2-b7e4-4435-ad1f-995d09fd60f8" 마커1
8 | # "10856e46-c224-41bb-961d-5c25c45b3122" 마커2
9 | # "c6ce5480-f883-49e6-86e7-cdff30fae2c1" 눈덩이
10 | /summon item_display ~ ~10 ~ {UUID:[I;-212156019,-1034207087,-1911127289,467150104],width:0f,height:0f,Tags:[dash.6626.item,dash.6626.entity],Passengers:[{id:"minecraft:snowball",UUID:[I;-959556480,-125613594,-2031628801,821748417],Tags:[dash.6626.snow,dash.6626.entity],Passengers:[{id:"minecraft:marker",Tags:[dash.6626.circ,dash.6626.circ1,dash.6626.entity],UUID:[I;1252287218,-1209777099,-1390438051,167600376]},{id:"minecraft:marker",Tags:[dash.6626.circ,dash.6626.circ2,dash.6626.entity],UUID:[I;277179974,-1037811269,-1776460763,-1000656606]}]}],item:{id:"minecraft:grass_block",count:1,components:{"minecraft:custom_data":{ejalepdlxj:1}}}}
11 | /execute positioned ~ ~10 ~ facing ^ ^1 ^ run tp "4aa462f2-b7e4-4435-ad1f-995d09fd60f8" ~ ~ ~ ~ ~
12 | /execute positioned ~ ~10 ~ facing ^ ^1 ^ facing ^ ^ ^-1 run tp "10856e46-c224-41bb-961d-5c25c45b3122" ~ ~ ~ ~ ~
13 | /execute positioned ~ ~10 ~ as "c6ce5480-f883-49e6-86e7-cdff30fae2c1" on passengers at @s positioned ^ ^ ^1 on vehicle on passengers rotated as @s positioned ^1 ^ ^ facing entity @s feet positioned as @s positioned ^ ^ ^1 on vehicle on passengers rotated as @s positioned ^ ^ ^1 facing entity @s feet positioned as @s positioned ^ ^ ^1 on vehicle on passengers rotated as @s positioned ^ ^ ^1 facing entity @s feet positioned as @s positioned ^ ^ ^1 on vehicle on passengers rotated as @s positioned ^ ^ ^1 facing entity @s feet positioned as @s positioned ^ ^ ^1 positioned as @s positioned ~ ~-10 ~ run particle minecraft:end_rod ~ ~ ~ ^ ^ ^100000000 .000000001 0
14 | /execute as "f35ac18d-c25b-4091-8e16-83071bd82518" on passengers on passengers run kill @s
15 | /execute as "f35ac18d-c25b-4091-8e16-83071bd82518" on passengers run kill @s
16 | /kill "f35ac18d-c25b-4091-8e16-83071bd82518"
17 |
18 | /execute if entity @s[gamemode=survival] run scoreboard players set gamemode 40planet_num 0
19 | /execute if entity @s[gamemode=creative] run scoreboard players set gamemode 40planet_num 1
20 | /execute if entity @s[gamemode=adventure] run scoreboard players set gamemode 40planet_num 2
21 | /gamemode creative
22 | /tp @s ~ ~1000 ~
23 | /execute at @s anchored eyes positioned ^ ^ ^-1 summon minecraft:end_crystal run damage @s 10
24 | /tp @s ~ ~ ~
25 |
26 |
27 | /execute if score gamemode 40planet_num matches 0 run gamemode survival
28 | /execute if score gamemode 40planet_num matches 1 run gamemode creative
29 | /execute if score gamemode 40planet_num matches 2 run gamemode adventure
30 | }
31 |
32 | def heal(){
33 | /effect give @s minecraft:instant_health 1 0 true
34 | }
35 | def resistance(){
36 | /effect give @s minecraft:resistance 5 0 true
37 | }
38 | def absorption(){
39 | /effect give @s minecraft:absorption 20 1 true
40 | }
41 | def berserker(){
42 | /damage @s 10 minecraft:out_of_world
43 | /effect give @s strength 10 1 true
44 | }
--------------------------------------------------------------------------------
/example/health_bar.planet:
--------------------------------------------------------------------------------
1 |
2 | /scoreboard objectives add 40planet_health dummy
3 | /scoreboard objectives add 40planet_pre_health dummy
4 | /scoreboard objectives add 40planet_max_health dummy
5 |
6 |
7 | def tick(){
8 | /execute as @e[tag=40planet_health_bar] run function __namespace__:tick_entity
9 | execute(as @e[tag=health_bar_display]){
10 | /scoreboard players set test 40planet_num 0
11 | /execute on vehicle if entity @s[tag=40planet_health_bar] run scoreboard players set test 40planet_num 1
12 | execute(if score "test" "40planet_num" matches 0 at @s){
13 | /execute on passengers run kill @s
14 | /kill @s
15 | }
16 | }
17 | }
18 |
19 | def detect(){
20 | /scoreboard players set test 40planet_num 0
21 | /execute on passengers on passengers if entity @s[tag=green] run scoreboard players set test 40planet_num 1
22 | execute(if score "test" "40planet_num" matches 0 at @s){
23 | /summon interaction ~ ~ ~ {Tags:["health_bar_display","unset"],height:0,width:0,Passengers:[{billboard:"vertical",transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],translation:[-1f,0.8f,0f],scale:[80f,8f,8f]},background:-16122112,Tags:["green"],id:"text_display",interpolation_duration:2,start_interpolation:0},{billboard:"vertical",transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],translation:[-1f,0.8f,-0.001f],scale:[80f,7.9f,7.9f]},background:-65536,Tags:["red"],id:"text_display"},{billboard:"vertical",transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],translation:[0f,1f,0f],scale:[1.5f,1.5f,1.5f]},background:0,Tags:["text"],shadow:1b,id:"text_display"}]}
24 | /ride @n[tag=unset] mount @s
25 | /execute on passengers run tag @s remove unset
26 | }
27 | }
28 |
29 | def set_health(){
30 | /execute store result score @s 40planet_health run data get entity @s Health
31 | execute(unless score "@s" "40planet_health" = "@s" "40planet_pre_health"){
32 | /execute store result storage 40planet:value health_bar.max_health float 0.01 run attribute @s minecraft:generic.max_health get 100
33 | var max_health = get_data("storage", "40planet:value", "health_bar.max_health")
34 | var health = get_data("entity", "@s", "Health")
35 | var percentage = health / max_health
36 | execute(on passengers on passengers){
37 | execute(if entity @s[tag=green]){
38 | /data modify entity @s start_interpolation set value 0
39 | set_data("entity", "@s", "transformation.scale[0]", percentage * float(80))
40 | }
41 | execute(if entity @s[tag=text]){
42 | set_score("@s", "40planet_health", health)
43 | set_score("@s", "40planet_max_health", max_health)
44 | /data merge entity @s {text:'["",{"score":{"name":"@s","objective":"40planet_health"},"color":"green"},{"text":"/","color":"green"},{"score":{"name":"@s","objective":"40planet_max_health"},"color":"green"}]'}
45 | }
46 | }
47 | }
48 |
49 | /scoreboard players operation @s 40planet_pre_health = @s 40planet_health
50 | }
51 |
52 | def tick_entity(){
53 | execute(if entity @s[type=player]){
54 | /tellraw @s {"text":"플레이어에게는 체력바를 표시할 수 없습니다", "color":"red"}
55 | return 0
56 | }
57 | detect()
58 | set_health()
59 | }
--------------------------------------------------------------------------------
/web/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;200;300;400;500;600;700;800;900&display=swap');
2 |
3 | * {
4 | box-sizing: border-box !important;
5 | }
6 |
7 | nav {
8 | display: flex;
9 | flex-direction: row;
10 | justify-content: space-between;
11 | align-items: center;
12 | }
13 |
14 | nav > img {
15 | width: 35px !important;
16 | }
17 |
18 | body {
19 | padding: 10px;
20 | font-family: "Noto Sans KR";
21 | background-color: aliceblue;
22 | }
23 |
24 | label {
25 | display: flex;
26 | flex-direction: row;
27 | gap: 5px;
28 | font-weight: 600;
29 | font-size: 23px;
30 | }
31 |
32 | img {
33 | width: 30px;
34 | }
35 |
36 | h1 {
37 | font-weight: 800;
38 | font-size: 35px;
39 | }
40 |
41 | #compile-btn {
42 | width: 100%;
43 | font-size: 18px;
44 | font-weight: 600;
45 | padding: 10px;
46 | background-color: dodgerblue;
47 | color: white;
48 | border-radius: 10px;
49 | border: 1px solid transparent;
50 |
51 | &:hover {
52 | background-color: rgb(54, 155, 255);
53 | }
54 | }
55 |
56 | #controller {
57 | margin-top: 15px;
58 | margin-bottom: 15px;
59 | }
60 |
61 | #controller > div {
62 | display: flex;
63 | flex-direction: column;
64 | margin-bottom: 10px;
65 | }
66 |
67 | #file {
68 | background-color: dodgerblue;
69 | font-size: 18px;
70 | padding: 10px 20px;
71 | color: white;
72 | border-radius: 10px;
73 | border: 1px solid transparent;
74 | font-weight: 600;
75 |
76 | &:hover {
77 | background-color: rgb(54, 155, 255);
78 | }
79 | }
80 |
81 | #folder {
82 | background-color: dodgerblue;
83 | font-size: 18px;
84 | padding: 10px 20px;
85 | color: white;
86 | border-radius: 10px;
87 | border: 1px solid transparent;
88 | font-weight: 600;
89 |
90 | &:hover {
91 | background-color: rgb(54, 155, 255);
92 | }
93 | }
94 |
95 | #version {
96 | font-size: 18px;
97 | background-color: rgba(30, 143, 255, 0.1);
98 | border: 1px solid #000000;
99 | border-radius: 5px;
100 | padding: 5px;
101 | }
102 |
103 | #namespace {
104 | font-size: 18px;
105 | background-color: rgba(30, 143, 255, 0.1);
106 | border: 1px solid #000000;
107 | border-radius: 5px;
108 | padding: 5px;
109 | }
110 |
111 | .button > div {
112 | display: flex;
113 | flex-direction: row;
114 | justify-content: space-between;
115 | align-items: center;
116 | }
117 |
118 | .button > div > div {
119 | display: flex;
120 | flex-direction: column;
121 | }
122 |
123 | .result {
124 | font-size: 15px;
125 | font-family: monospace;
126 | font-weight: 600;
127 | }
128 |
129 | .warning {
130 | color: red;
131 | font-weight: 600;
132 | }
133 |
134 | .compile-error-result {
135 | margin-top: 10px;
136 | font-family: monospace;
137 | width: 100%;
138 | height: 300px;
139 | background-color: rgba(30, 143, 255, 0.1);
140 | border: 1px solid #000000;
141 | border-radius: 10px;
142 | padding: 5px;
143 | overflow-wrap: break-word;
144 | white-space: break-spaces;
145 | }
146 |
147 | #output {
148 | margin-top: 10px;
149 | width: 100%;
150 | display: flex;
151 | flex-direction: column;
152 | }
153 |
154 | #output-show-output {
155 | background-color: dodgerblue;
156 | font-size: 18px;
157 | padding: 10px 20px;
158 | color: white;
159 | border-radius: 10px;
160 | border: 1px solid transparent;
161 | font-weight: 600;
162 |
163 | &:hover {
164 | background-color: rgb(54, 155, 255);
165 | }
166 | }
167 |
168 | code {
169 | font-weight: 600;
170 | font-size: 15px;
171 | }
--------------------------------------------------------------------------------
/rpg_planet/mob/health_bar.planet:
--------------------------------------------------------------------------------
1 |
2 | /scoreboard objectives add 40planet_health_bar_health dummy
3 | /scoreboard objectives add 40planet_pre_health dummy
4 | /scoreboard players set 10 40planet_num 10
5 | /scoreboard players set -1 40planet_num -1
6 |
7 |
8 | def health_bar_tick(){
9 | /function __namespace__:tick_entity
10 | execute(as @s[tag=health_bar_display] unless predicate rpg_mob:vehicle){
11 | /execute on passengers run kill @s
12 | /kill @s
13 | }
14 | }
15 |
16 | def detect(){
17 | /scoreboard players set test 40planet_num 0
18 | /execute on passengers on passengers if entity @s[tag=green] run scoreboard players set test 40planet_num 1
19 | execute(if score "test" "40planet_num" matches 0 at @s){
20 | /summon interaction ~ ~ ~ {Tags:["health_bar_display","unset"],height:0,width:0,Passengers:[{billboard:"vertical",transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],translation:[-1f,0.8f,0f],scale:[80f,8f,8f]},background:-16122112,Tags:["green"],id:"text_display",interpolation_duration:2,start_interpolation:0},{billboard:"vertical",transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],translation:[-1f,0.8f,-0.001f],scale:[80f,7.9f,7.9f]},background:-65536,Tags:["red"],id:"text_display"},{billboard:"vertical",transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],translation:[0f,1f,0f],scale:[1.5f,1.5f,1.5f]},background:0,Tags:["text"],shadow:1b,id:"text_display"}]}
21 | /ride @n[distance=..0.001,tag=unset] mount @s
22 | /execute on passengers run tag @s remove unset
23 | }
24 | }
25 |
26 | def set_health(){
27 | /execute store result score @s 40planet_health_bar_health run data get entity @s Health 10
28 | execute(unless score "@s" "40planet_health_bar_health" = "@s" "40planet_pre_health"){
29 | /scoreboard players operation @s 40planet_pre_health = @s 40planet_health_bar_health
30 | var max_health = get_score("@s", "40planet_rpg_health")
31 | /scoreboard players operation @s 40planet_health_bar_health = @s 40planet_rpg_health
32 | /scoreboard players operation @s 40planet_health_bar_health -= @s 40planet_reduced_health
33 | var health = get_score("@s", "40planet_health_bar_health")
34 | print("max_health :", max_health, "health :", health)
35 | var percentage = divide(health, max_health)
36 | /scoreboard players operation health 40planet_num = @s 40planet_health_bar_health
37 | /scoreboard players operation health 40planet_num /= 10 40planet_num
38 | /scoreboard players operation max_health 40planet_num = @s 40planet_rpg_health
39 | /scoreboard players operation max_health 40planet_num /= 10 40planet_num
40 | execute(on passengers on passengers){
41 | execute(if entity @s[tag=green]){
42 | /data modify entity @s start_interpolation set value 0
43 | set_data("entity", "@s", "transformation.scale[0]", float(percentage * 80.0))
44 | print("percentage :", percentage, "scale :", float(percentage * 80.0))
45 | }
46 | execute(if entity @s[tag=text]){
47 | /data merge entity @s {text:'["",{"score":{"name":"health","objective":"40planet_num"},"color":"green"},{"text":"/","color":"green"},{"score":{"name":"max_health","objective":"40planet_num"},"color":"green"}]'}
48 | }
49 | }
50 | }
51 |
52 | }
53 |
54 | def tick_entity(){
55 | execute(if entity @s[type=player]){
56 | /tellraw @s {"text":"플레이어에게는 체력바를 표시할 수 없습니다", "color":"red"}
57 | return 0
58 | }
59 | detect()
60 | execute(if data entity "@s" "Health"){ set_health() }
61 | }
--------------------------------------------------------------------------------
/consts.py:
--------------------------------------------------------------------------------
1 | import os
2 | from lark import Token, Lark
3 |
4 | SCORE_TYPES = ("int", "float", "double", "bool")
5 | MINECRAFT_TYPES = ("bool", "short", "int", "float", "double", "long")
6 | TYPES = ("entity", "nbt", "string") + SCORE_TYPES
7 | SCOREBOARD_NAME = "40planet_num"
8 | STORAGE_NAME = "40planet:value"
9 | NAMESPACE = "__namespace__"
10 | MAIN_NAMESPACE = "__main__"
11 | DIGITS = '0123456789'
12 |
13 | INTERPRETE_THESE = ("operator", "call_function", "make_array", "make_nbt", "make_selector", "define_var")
14 |
15 | BUILT_IN_FUNCTION = ("print", "random", "type", "get_score", "get_data", "set_score", "set_data", "round", "del", "append", "is_module", "len", "divide", "multiply") + TYPES
16 |
17 | OPERATOR_ID = {
18 | "+":1,
19 | "-":2,
20 | "*":3,
21 | "/":4,
22 | "%":5,
23 | "==":6,
24 | "!=":7,
25 | ">=":8,
26 | ">":9,
27 | "<=":10,
28 | "<":11,
29 | "!":12,
30 | "member":13,
31 | # ".":14
32 | }
33 |
34 | CNAME = 'CNAME'
35 | INT = 'INT'
36 | ESCAPED_STRING = 'ESCAPED_STRING'
37 | OPERATION = "operation"
38 |
39 | NEW_LINE = "䗻"
40 |
41 | lark_directory = os.path.join(os.path.dirname(__file__), "grammer.lark")
42 |
43 | with open(lark_directory, encoding="utf-8") as f:
44 | grammar = f.read()
45 |
46 | planet_parser = Lark(
47 | grammar,
48 | parser="lalr", # Earley -> LALR (대폭 가속)
49 | # parser="earley", # Earley -> LALR (대폭 가속)
50 | lexer="contextual", # 토큰 충돌시 백트래킹 감소
51 | start="start", # 프로젝트의 시작 심볼로 교체
52 | propagate_positions=True, # 에러/디버깅 편의
53 | maybe_placeholders=False, # 불필요한 None 삽입 방지(속도↑)
54 | cache=True, # 문법 분석 캐시 (초기화 속도↑)
55 | debug=True
56 | )
57 |
58 |
59 |
60 | #######################################
61 | # ERRORS
62 | #######################################
63 |
64 | def error_as_txt(token, error_name, filename, details, line = ""):
65 | print(type(token))
66 | with open(filename, "r", encoding="utf-8") as file:
67 | line = file.read().split("\n")[token.line - 1]
68 |
69 | result = f'{error_name}: {details}\n'
70 | result += f'File {filename}, line {token.line}, col {token.column - 1}'
71 | result += "\n\n" + line
72 | if line[-1] != "\n": result += "\n"
73 | result += " " * (token.column - 1)
74 | result += "^" * (token.end_pos - token.start_pos)
75 | return result
76 |
77 | #######################################
78 | # VARIABLE
79 | #######################################
80 |
81 | class VariableComet:
82 | def __init__(self, name, temp = "", details = None) -> None:
83 | self.name = name
84 | self.temp = temp
85 | self.details = details
86 |
87 | def __repr__(self):
88 | return f"({self.name}, {self.temp})"
89 |
90 | class Function:
91 | def __init__(self, name, type_, inputs, temp) -> None:
92 | self.name = name
93 | self.type = type_
94 | self.inputs = inputs
95 | self.temp = temp
96 | def __repr__(self) -> str:
97 | return f"name: {self.name}, temp: {self.temp}, inputs: {self.inputs}"
98 |
99 | class CometToken:
100 | def __init__(self, type_, value, start_pos = None, line = None, column = None, end_line = None, end_column = None, end_pos = None, command = None):
101 | self.tok = Token(type_, value, start_pos, line, column, end_line, end_column, end_pos)
102 | self.command = command
103 | self.type = type_
104 | self.value = value
105 | self.start_pos = start_pos
106 | self.line = line
107 | self.column = column
108 | self.end_line = end_line
109 | self.end_column = end_column
110 | self.end_pos = end_pos
111 |
112 | def __repr__(self):
113 | return f"CometToken(type:{self.type}, value:{self.value}, command:{self.command})"
114 |
115 | class CometClass:
116 | def __init__(self):
117 | self.method = []
118 | self.variables = []
--------------------------------------------------------------------------------
/rpg_planet/stat.planet:
--------------------------------------------------------------------------------
1 | /scoreboard objectives add 40planet_rpg_level dummy
2 | /scoreboard objectives add 40planet_level level
3 | /scoreboard objectives add 40planet_stat_point dummy
4 | /scoreboard objectives add 40planet_rpg_health dummy
5 | /scoreboard objectives add 40planet_rpg_strength dummy
6 | /scoreboard objectives add 40planet_rpg_speed dummy
7 | /scoreboard objectives add 40planet_rpg_mana dummy
8 |
9 | /scoreboard players set point_per_level 40planet_num 1
10 |
11 | def tick(){
12 | execute(as @a){
13 | /execute unless score @s 40planet_rpg_level = @s 40planet_rpg_level run function __namespace__:set_scoreboard
14 | execute(if score "@s" "40planet_level" > "@s" "40planet_rpg_level"){ # 레벨업
15 | /scoreboard players operation temp 40planet_num = @s 40planet_level
16 | /scoreboard players operation temp 40planet_num -= @s 40planet_rpg_level
17 | /scoreboard players operation temp 40planet_num *= point_per_level 40planet_num
18 | /scoreboard players operation @s 40planet_stat_point += temp 40planet_num
19 | /scoreboard players operation @s 40planet_rpg_level = @s 40planet_level
20 | /function __namespace__:save
21 | }
22 | }
23 | }
24 |
25 | def update_attribute(){
26 | var health = get_score("@s", "40planet_rpg_health") + 20
27 | var strength = get_score("@s", "40planet_rpg_strength") + 1
28 | /scoreboard players add @s 40planet_rpg_speed 20
29 | var speed = multiply(get_score("@s", "40planet_rpg_speed"), 0.005)
30 | var mining_speed = multiply(get_score("@s", "40planet_rpg_speed"), 0.05)
31 | /scoreboard players remove @s 40planet_rpg_speed 20
32 | /attribute @s minecraft:generic.max_health base set ^health&
33 | /attribute @s minecraft:generic.attack_damage base set ^strength&
34 | /attribute @s minecraft:generic.movement_speed base set ^speed&
35 | /attribute @s minecraft:player.block_break_speed base set ^mining_speed&
36 | }
37 |
38 | def set_scoreboard(){
39 | var uuid = get_data("entity", "@s", "UUID")
40 | /scoreboard players set is_uuid_exist 40planet_num 0
41 | /execute if data storage 40planet:stat player."^uuid&".id run scoreboard players set is_uuid_exist 40planet_num 1
42 | # uuid가 있을 때
43 | execute(if score "is_uuid_exist" "40planet_num" matches 1){
44 | /execute store result score @s 40planet_rpg_level run data get storage 40planet:stat player."^uuid&".level
45 | /execute store result score @s 40planet_rpg_health run data get storage 40planet:stat player."^uuid&".health
46 | /execute store result score @s 40planet_rpg_strength run data get storage 40planet:stat player."^uuid&".strength
47 | /execute store result score @s 40planet_rpg_speed run data get storage 40planet:stat player."^uuid&".speed
48 | /execute store result score @s 40planet_rpg_mana run data get storage 40planet:stat player."^uuid&".mana
49 | /execute store result score @s 40planet_stat_point run data get storage 40planet:stat player."^uuid&".stat_point
50 | }
51 | # uuid가 없을 때
52 | execute(if score "is_uuid_exist" "40planet_num" matches 0){
53 | /scoreboard players set @s 40planet_rpg_level 0
54 | /scoreboard players set @s 40planet_rpg_health 0
55 | /scoreboard players set @s 40planet_rpg_strength 0
56 | /scoreboard players set @s 40planet_rpg_speed 0
57 | /scoreboard players set @s 40planet_rpg_mana 0
58 | /scoreboard players set @s 40planet_stat_point 0
59 | /data modify storage 40planet:stat player."^uuid&" set value {health:0,level:0,strength:0,speed:0,mana:0,stat_point:0}
60 | }
61 | }
62 |
63 | def save_all(){
64 | /execute as @a run function __namespace__:save
65 | }
66 | def save(){
67 | var uuid = get_data("entity", "@s", "UUID")
68 | /execute store result storage 40planet:stat player.uuid.level int 1 run scoreboard players get @s 40planet_rpg_level
69 | /execute store result storage 40planet:stat player.uuid.health int 1 run scoreboard players get @s 40planet_rpg_health
70 | /execute store result storage 40planet:stat player.uuid.strength int 1 run scoreboard players get @s 40planet_rpg_strength
71 | /execute store result storage 40planet:stat player.uuid.speed int 1 run scoreboard players get @s 40planet_rpg_speed
72 | /execute store result storage 40planet:stat player.uuid.mana int 1 run scoreboard players get @s 40planet_rpg_mana
73 | /execute store result storage 40planet:stat player.uuid.stat_point int 1 run scoreboard players get @s 40planet_stat_point
74 | /data modify storage 40planet:stat player."^uuid&" set from storage 40planet:stat player.uuid
75 | }
76 |
77 | def reset(){
78 | var uuid = get_data("entity", "@s", "UUID")
79 | /data remove storage 40planet:stat player."^uuid&"
80 | /scoreboard players set @s 40planet_rpg_level 0
81 | /scoreboard players set @s 40planet_rpg_health 0
82 | /scoreboard players set @s 40planet_rpg_strength 0
83 | /scoreboard players set @s 40planet_rpg_speed 0
84 | /scoreboard players set @s 40planet_rpg_mana 0
85 | /scoreboard players set @s 40planet_stat_point 0
86 | /data modify storage 40planet:stat player."^uuid&" set value {health:0,level:0,strength:0,speed:0,mana:0,stat_point:0}
87 | update_attribute()
88 | save()
89 | }
--------------------------------------------------------------------------------
/example/animation.planet:
--------------------------------------------------------------------------------
1 | /scoreboard objectives add 40planet_ani dummy
2 | /scoreboard objectives add 40planet_ani_end_time dummy
3 |
4 | def summon(){
5 | /# 소환 커맨드
6 | execute(as @e[distance=..0.0001,tag=unset]){
7 | /scoreboard players set @s ani_end_time 50
8 | /execute on passengers run data modify entity @s interpolation_duration set value 10
9 | }
10 | }
11 |
12 | def tick(){
13 | execute(as @e[tag=40planet_animation,scores={40planet_ani=0..}]){
14 | /scoreboard players add @s 40planet_ani 1
15 | /execute if score @s 40planet_ani > @s ani_end_time run scoreboard players reset @s 40planet_ani
16 | /execute if score @s 40planet_ani matches 20 on passengers run function __namespace__:frame_1
17 | /execute if score @s 40planet_ani matches 40 on passengers run function __namespace__:frame_2
18 | }
19 | }
20 |
21 | def frame_1(){
22 | /execute if entity @s[tag=1] run data modify entity @s transformation.scale set value [1f,2f,1f]
23 | /execute if entity @s[tag=2] run data modify entity @s transformation.translation set value [1f,0f,0f]
24 | }
25 | def frame_2(){
26 | /execute if entity @s[tag=1] run data modify entity @s transformation.scale set value [1f,1f,1f]
27 | /execute if entity @s[tag=2] run data modify entity @s transformation.translation set value [0f,0f,0f]
28 | }
29 |
30 | # def set_mawang_transformation(){
31 | # /execute if entity @s[tag=mawang_believer1,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.1212,0.0,0.4217,-0.2186,0.3762,-0.0,-0.2186,-0.4217,0.0544,0.0,0.0,0.0,1.0], }
32 | # /execute if entity @s[tag=mawang_believer2,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.1131,0.0,0.4199,0.3359,0.3044,-0.0,0.4199,-0.3359,0.1994,0.0,0.0,0.0,1.0], }
33 | # /execute if entity @s[tag=mawang_believer3,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.1,0.0,0.0,0.475,0.1238,0.0,0.5937,-0.0,0.0519,0.0,0.0,0.0,1.0], }
34 | # /execute if entity @s[tag=mawang_believer4,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,-0.1137,0.0,0.4217,-0.2186,0.3762,-0.0,-0.2186,-0.4217,0.0544,0.0,0.0,0.0,1.0], }
35 | # /execute if entity @s[tag=mawang_believer5,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,-0.0,-0.1062,0.0,0.4199,0.3359,0.3044,0.0,0.4199,-0.3359,0.1994,0.0,0.0,0.0,1.0], }
36 | # /execute if entity @s[tag=mawang_believer6,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,-0.0956,-0.0,-0.0,0.475,0.1237,0.0,0.5938,0.0,0.0519,0.0,0.0,0.0,1.0], }
37 | # /execute if entity @s[tag=mawang_believer7,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.3559,-0.0,-0.4675,0.0841,0.8687,0.0,0.0841,0.4675,-0.0627,0.0,0.0,0.0,1.0], }
38 | # /execute if entity @s[tag=mawang_believer8,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.3559,-0.0,-0.4675,0.0841,1.1006,0.0,0.0841,0.4675,-0.1045,0.0,0.0,0.0,1.0], }
39 | # /execute if entity @s[tag=mawang_believer9,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.3559,-0.0,-0.4675,0.0841,1.3325,0.0,0.0841,0.4675,-0.1462,0.0,0.0,0.0,1.0], }
40 | # /execute if entity @s[tag=mawang_believer10,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,-0.356,-0.0,-0.4675,0.0841,0.8687,0.0,0.0841,0.4675,-0.0627,0.0,0.0,0.0,1.0], }
41 | # /execute if entity @s[tag=mawang_believer11,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,-0.356,-0.0,-0.4675,0.0841,1.1006,0.0,0.0841,0.4675,-0.1045,0.0,0.0,0.0,1.0], }
42 | # /execute if entity @s[tag=mawang_believer12,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,-0.356,-0.0,-0.4675,0.0841,1.3325,0.0,0.0841,0.4675,-0.1462,0.0,0.0,0.0,1.0], }
43 | # /execute if entity @s[tag=mawang_believer13,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,-0.1185,0.0,0.4675,-0.0841,1.0114,-0.0,-0.0841,-0.4675,-0.0737,0.0,0.0,0.0,1.0], }
44 | # /execute if entity @s[tag=mawang_believer14,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.1185,0.0,0.4675,-0.0841,1.0114,-0.0,-0.0841,-0.4675,-0.0737,0.0,0.0,0.0,1.0], }
45 | # /execute if entity @s[tag=mawang_believer15,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,-0.1185,0.0,0.4675,-0.0841,0.7795,-0.0,-0.0841,-0.4675,-0.0319,0.0,0.0,0.0,1.0], }
46 | # /execute if entity @s[tag=mawang_believer16,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.1185,0.0,0.4675,-0.0841,0.7795,-0.0,-0.0841,-0.4675,-0.0319,0.0,0.0,0.0,1.0], }
47 | # /execute if entity @s[tag=mawang_believer17,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,-0.1185,0.0,0.4675,-0.0841,0.5476,-0.0,-0.0841,-0.4675,0.0098,0.0,0.0,0.0,1.0], }
48 | # /execute if entity @s[tag=mawang_believer18,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.475,0.0,0.0,0.1185,0.0,0.4675,-0.0841,0.5476,-0.0,-0.0841,-0.4675,0.0098,0.0,0.0,0.0,1.0], }
49 | # /execute if entity @s[tag=mawang_believer19,type=item_display] run data merge entity @s {start_interpolation: 0, interpolation_duration: 10, transformation:[-0.95,0.0,0.0,0.0,0.0,0.8719,-0.3773,1.3902,-0.0,-0.3773,-0.8719,-0.2487,0.0,0.0,0.0,1.0], }
50 | # }
--------------------------------------------------------------------------------
/rpg_planet/skill.planet:
--------------------------------------------------------------------------------
1 |
2 | # /scoreboard objectives add 40planet_mana_regeneration dummy
3 | /scoreboard objectives add 40planet_real_mana dummy
4 | /scoreboard objectives add 40planet_mana dummy
5 | /scoreboard objectives add 40planet_rpg_max_mana dummy
6 | /scoreboard objectives add 40planet_rpg_rightclick dummy
7 |
8 | /scoreboard players set 20 40planet_num 20
9 | /scoreboard players set 200 40planet_num 200
10 |
11 | def execute_function(var skill_slot){
12 | /item replace block 15 -60 15 container.0 from entity @s weapon
13 | /data modify storage 40planet:rpg skill set from block 15 -60 15 Items[0].components.'minecraft:custom_data'.skill.^skill_slot&
14 |
15 | /execute store result score current_game_tick 40planet_num run time query gametime
16 | /execute store result score recent_used 40planet_num run data get storage 40planet:rpg skill.components.'minecraft:custom_data'.recent_used
17 | /execute store result score cooltime 40planet_num run data get storage 40planet:rpg skill.components.'minecraft:custom_data'.cooltime
18 |
19 | /scoreboard players operation current_game_tick 40planet_num -= recent_used 40planet_num
20 | execute(if score "current_game_tick" "40planet_num" < "cooltime" "40planet_num"){
21 | /tellraw @s {"text":"쿨타임이 남았습니다","color":"red"}
22 | return 0
23 | }
24 |
25 | /execute store result score require_mana 40planet_num run data get storage 40planet:rpg skill.components.'minecraft:custom_data'.mana
26 | execute(if score "@s" "40planet_mana" < "require_mana" "40planet_num"){
27 | /tellraw @s {"text":"마나가 부족합니다","color":"red"}
28 | return 0
29 | }
30 |
31 |
32 | /execute store result storage 40planet:rpg skill.components.'minecraft:custom_data'.recent_used int 1 run time query gametime
33 | /scoreboard players operation @s 40planet_mana -= require_mana 40planet_num
34 | /data modify block 15 -60 15 Items[0].components.'minecraft:custom_data'.skill.^skill_slot& set from storage 40planet:rpg skill
35 | /item replace entity @s weapon from block 15 -60 15 container.0
36 | var function = get_data("storage", "40planet:rpg", "skill.components.'minecraft:custom_data'.function")
37 | # print(function)
38 | /execute at @s run function ^function&
39 | }
40 |
41 | def weapon_f(){
42 | /item replace block 15 -60 15 container.0 from entity @s weapon.offhand
43 | /scoreboard players set temp 40planet_num 0
44 | /execute if items entity @s weapon *[minecraft:custom_data~{40planet_equipment:1b}] run scoreboard players set temp 40planet_num 1
45 | execute(if score "temp" "40planet_num" matches 1){
46 | /item replace block 15 -60 15 container.1 from entity @s weapon
47 | /item replace entity @s weapon from entity @s weapon.offhand
48 | /item replace entity @s weapon.offhand with air
49 | /execute at @s run summon item ~ ~1.5 ~ {PickupDelay:0s,Item:{id:"stone",count:1b},Tags:["40planet_rpg_item"]}
50 | execute(as @e[tag=40planet_rpg_item,limit=1]){
51 | /item replace entity @s container.0 from block 15 -60 15 container.1
52 | /tag @s remove 40planet_rpg_item
53 | }
54 | }
55 | execute(if score "temp" "40planet_num" matches 0){
56 | /item replace entity @s weapon.offhand from entity @s weapon
57 | /item replace entity @s weapon from block 15 -60 15 container.0
58 | }
59 |
60 | execute(if data entity "@s" "SelectedItem.components.'minecraft:custom_data'.skill.f.components.'minecraft:custom_data'.function"){
61 | execute_function("f")
62 | }
63 | }
64 |
65 | def rightclick_advancement(){
66 | /scoreboard players set @s 40planet_rpg_rightclick 1
67 | /advancement revoke @s only rpg:rightclick
68 | }
69 |
70 | def rightclick(){
71 | /execute unless items entity @s weapon *[minecraft:custom_data~{40planet_equipment:1b}] run return fail
72 | /tag @s add rightclick
73 |
74 | execute(if predicate rpg:sneaking if data entity "@s" "SelectedItem.components.'minecraft:custom_data'.skill.sneak_click.components.'minecraft:custom_data'.function"){
75 | execute_function("sneak_click")
76 | # var function = get_data("entity", "@s", "SelectedItem.components.'minecraft:custom_data'.skill.sneak_click.components.'minecraft:custom_data'.function")
77 | # /execute at @s run function ^function&
78 | }
79 | execute(unless predicate rpg:sneaking if data entity "@s" "SelectedItem.components.'minecraft:custom_data'.skill.click.components.'minecraft:custom_data'.function"){
80 | execute_function("click")
81 | # var function = get_data("entity", "@s", "SelectedItem.components.'minecraft:custom_data'.skill.click.components.'minecraft:custom_data'.function")
82 | # /execute at @s run function ^function&
83 | }
84 | }
85 |
86 |
87 |
88 | def tick(){
89 | execute(as @a){
90 | # F 스킬 감지
91 | /execute if items entity @s weapon.offhand *[minecraft:custom_data~{40planet_equipment:1b}] run function __namespace__:weapon_f
92 | # 우클릭 감지
93 | /execute if score @s[tag=!rightclick] 40planet_rpg_rightclick matches 1 run function __namespace__:rightclick
94 | /execute if score @s 40planet_rpg_rightclick matches 0 run tag @s remove rightclick
95 |
96 | # 마나 회복
97 | # 마나 스텟 1 = 10 최대마나, 1초당 1 마나 회복 = 1틱 당 1/20 마나 회복 = 틱당 1 real_mana 회복
98 | # real_mana = mana * 20
99 | # /scoreboard players operation @s 40planet_mana_regeneration = @s 40planet_rpg_mana
100 | /scoreboard players operation @s 40planet_rpg_max_mana = @s 40planet_rpg_mana
101 | /scoreboard players operation @s 40planet_rpg_max_mana += @s 40planet_rpg_equipment_mana
102 | /scoreboard players operation @s 40planet_rpg_max_mana *= 200 40planet_num
103 |
104 | /scoreboard players operation temp 40planet_mana = @s 40planet_real_mana
105 | /scoreboard players operation temp 40planet_mana /= 20 40planet_num
106 | execute(unless score "temp" "40planet_mana" = "@s" "40planet_mana"){
107 | /scoreboard players operation @s 40planet_real_mana = @s 40planet_mana
108 | /scoreboard players operation @s 40planet_real_mana *= 20 40planet_num
109 | }
110 | # /scoreboard players operation @s 40planet_real_mana += @s 40planet_mana_regeneration
111 | /scoreboard players operation @s 40planet_real_mana += @s 40planet_rpg_mana
112 | /scoreboard players operation @s 40planet_real_mana += @s 40planet_rpg_equipment_mana
113 | /execute if score @s 40planet_real_mana > @s 40planet_rpg_max_mana run scoreboard players operation @s 40planet_real_mana = @s 40planet_rpg_max_mana
114 | /scoreboard players operation @s 40planet_mana = @s 40planet_real_mana
115 | /scoreboard players operation @s 40planet_mana /= 20 40planet_num
116 |
117 | /execute if entity @s[tag=show_mana] run title @s actionbar [{"text":"현재 마나: ","color":"aqua"},{"score":{"objective":"40planet_mana","name":"@s"}}]
118 | }
119 | /scoreboard players set @a 40planet_rpg_rightclick 0
120 | }
--------------------------------------------------------------------------------
/rpg_planet/camera.planet:
--------------------------------------------------------------------------------
1 |
2 | var camera_paths
3 | var selected_path
4 | /scoreboard players set rot_x 40planet_camera_num 200
5 | /scoreboard players set rot_y 40planet_camera_num 200
6 |
7 | def get_wand(){
8 | /give @p minecraft:stick[minecraft:custom_data={40planet_wand:1b},minecraft:food={nutrition:0,saturation:0,can_always_eat:true,eat_seconds:2147483647}]
9 | }
10 |
11 | def first_load(){
12 | /scoreboard objectives add 40planet_camera_num dummy
13 | /scoreboard objectives add 40planet_camera_timer dummy
14 | /scoreboard objectives add 40planet_camera_is_playing dummy
15 | /scoreboard objectives add 40planet_camera_point_num dummy
16 | /scoreboard objectives add 40planet_id dummy
17 | camera_paths = []
18 | /scoreboard players set is_selected 40planet_camera_num 0
19 | /execute as @a store result score @s 40planet_id run scoreboard players add #first 40planet_id 1
20 | /scoreboard objectives add 40planet_camera_stick_drop minecraft.dropped:minecraft.stick
21 | /scoreboard players set rot_x 40planet_camera_num 200
22 | /scoreboard players set rot_y 40planet_camera_num 200
23 | selected_path = 0
24 | }
25 |
26 | def play(var idx){
27 | var camera_path = camera_paths[idx]
28 | /scoreboard players set @s 40planet_camera_is_playing 1
29 | /scoreboard players set @s 40planet_camera_point_num 0
30 | set_score("@s", "40planet_camera_timer", camera_path[0][3])
31 | }
32 |
33 | def add_path(){ append(camera_paths, []) }
34 | def remove_path(var num){ del(camera_paths[num]) }
35 | def add_point(var x, var y, var z, var r1, var r2, var t){ append(camera_paths[selected_path], [x, y, z, r1, r2, t]) }
36 | def remove_point(var num, var num2){ del(camera_paths[num][num2]) }
37 |
38 | def summon_point(){
39 | execute( positioned ~ ~1.5 ~ summon item_display){
40 | /data merge entity @s {item:{id:"dropper",Count:1b},Tags:["40planet_camera_marker"]}
41 | var point_idx = len(camera_paths[selected_path])
42 | print(point_idx)
43 | set_data("entity", "@s", "item.components.minecraft:custom_data.point_idx", point_idx)
44 | }
45 | add_point(get_data("entity", "@s", "Pos[0]"), get_data("entity", "@s", "Pos[1]") + 1.5, get_data("entity", "@s", "Pos[2]"), get_data("entity", "@s", "Rotation[0]"), get_data("entity", "@s", "Rotation[1]"), 20)
46 | }
47 |
48 | def next_point(){
49 | /scoreboard players add @s 40planet_camera_point_num 1
50 | var point_idx = get_score("@s", "40planet_camera_point_num")
51 | var path_idx = get_score("@s", "40planet_camera_num")
52 | execute(unless data camera_paths[path_idx][point_idx]){
53 | /scoreboard players set @s 40planet_camera_is_playing 0
54 | return 0
55 | }
56 | var point = camera_paths[path_idx][point_idx]
57 | print(point)
58 | }
59 |
60 |
61 | def unselect_all(){
62 | execute(as @e[tag=40planet_camera_selected_marker]){
63 | /tag @s remove 40planet_camera_selected_marker
64 | /data modify entity @s Glowing set value 0
65 | }
66 | /scoreboard players set is_selected 40planet_camera_num 0
67 | }
68 |
69 |
70 | def tick_player(){
71 | execute(if score "@s" "40planet_camera_is_playing" matches 1){ # 재생 중인 플레이어라면
72 | /scoreboard players remove @s 40planet_camera_timer 1
73 | /execute if score @s 40planet_camera_timer matches ..0 run function __namespace__:next_point
74 | }
75 |
76 | execute(if items entity @s weapon.mainhand minecraft:stick[minecraft:custom_data={40planet_wand:1b}]){
77 | execute( unless entity @s[tag=40planet_click_wand] ) {
78 | /scoreboard players set rot_x 40planet_camera_num 200
79 | }
80 | /execute if entity @s[tag=40planet_click_wand] run tag @s remove 40planet_click_wand
81 | }
82 |
83 | execute(if items entity @s weapon.offhand minecraft:stick[minecraft:custom_data={40planet_wand:1b}]){
84 | /item replace entity @s weapon.mainhand from entity @s weapon.offhand
85 | /item replace entity @s weapon.offhand with air
86 | execute(as @e[tag=40planet_camera_selected_marker]){
87 | var point_idx = get_data("entity", "@s", "item.components.minecraft:custom_data.point_idx")
88 | #print(point_idx)
89 | del(camera_paths[selected_path][point_idx])
90 | /kill @s
91 | /scoreboard players set is_selected 40planet_camera_num 0
92 | }
93 | }
94 |
95 | execute(if score "@s" "40planet_camera_stick_drop" matches 1..){
96 | execute(as @e[tag=40planet_camera_selected_marker]){
97 | var point_idx = get_data("entity", "@s", "item.components.minecraft:custom_data.point_idx")
98 | var rotation = get_data("entity", "@s", "Rotation")
99 | camera_paths[selected_path][point_idx][3] = rotation[0]
100 | camera_paths[selected_path][point_idx][4] = rotation[1]
101 |
102 | }
103 | unselect_all()
104 | get_wand()
105 | /kill @e[type=item,nbt={Item:{components:{"minecraft:custom_data":{40planet_wand:1b}}}}]
106 | /scoreboard players set @s 40planet_camera_stick_drop 0
107 | }
108 | }
109 |
110 | /advancement revoke @s only __namespace__:using_wand
111 | def click_wand(){
112 | /advancement revoke @s only __namespace__:using_wand
113 | /execute unless items entity @s weapon.mainhand minecraft:stick[minecraft:custom_data={40planet_wand:1b}] run return 0
114 | /tag @s add 40planet_click_wand
115 | execute( if score "is_selected" "40planet_camera_num" matches 0 ){ # 바라보고 있는 마커 선택
116 | unselect_all()
117 | /scoreboard players set #temp 40planet_camera_num 0
118 | /tag @s add this
119 | execute( as @e[tag=40planet_camera_marker] positioned as @s facing entity @p[tag=this] feet positioned ^ ^ ^1 rotated as @p[tag=this] positioned ^ ^ ^1 if entity @s[distance=..0.5] ){
120 | /execute if score #temp 40planet_camera_num matches 1 run return 0
121 | /tag @s add 40planet_camera_selected_marker
122 | /data modify entity @s Glowing set value 1b
123 | /scoreboard players set is_selected 40planet_camera_num 1
124 | /scoreboard players set #temp 40planet_camera_num 1
125 | }
126 | /tag @s remove this
127 | return 0
128 | }
129 | /execute store result score player_x 40planet_camera_num run data get entity @s Rotation[0]
130 | /execute store result score player_y 40planet_camera_num run data get entity @s Rotation[1]
131 | execute( if score "rot_x" "40planet_camera_num" matches 200 ){
132 | execute( as @e[tag=40planet_camera_selected_marker] ){
133 | /execute store result score rot_x 40planet_camera_num run data get entity @s Rotation[0]
134 | /execute store result score rot_y 40planet_camera_num run data get entity @s Rotation[1]
135 | }
136 | /scoreboard players operation rot_x 40planet_camera_num -= player_x 40planet_camera_num
137 | /scoreboard players operation rot_y 40planet_camera_num -= player_y 40planet_camera_num
138 | }
139 | execute( as @e[tag=40planet_camera_selected_marker] ){
140 | /execute store result entity @s Rotation[0] float 1 run scoreboard players operation player_x 40planet_camera_num += rot_x 40planet_camera_num
141 | /execute store result entity @s Rotation[1] float 1 run scoreboard players operation player_y 40planet_camera_num += rot_y 40planet_camera_num
142 | }
143 | }
144 |
145 | def tick(){
146 | if( is_module() ){ return 0 }
147 | execute(as @a){ tick_player() }
148 | }
149 |
150 |
151 |
152 |
153 | if( !(is_module()) ){
154 | /execute unless score #first 40planet_id = #first 40planet_id run function __namespace__:first_load
155 | }
156 |
157 | def test(){
158 | /scoreboard players set @s 40planet_camera_num 1
159 | play(get_score("@s", "40planet_camera_num"))
160 | }
--------------------------------------------------------------------------------
/README_en.md:
--------------------------------------------------------------------------------
1 | # Datapack-Compiler
2 | This project is a Minecraft datapack compiler.
3 | Developed by **40planet**, free to use as long as proper credit is given.
4 |
5 | - [Usage](#usage)
6 | - [VSCode Syntax Highlighting Extension](#vscode-syntax-highlighting-extension)
7 | - [Contributing](#contributing)
8 | - [Grammar](#grammar)
9 | - [General](#general)
10 | - [execute](#execute)
11 | - [import](#import)
12 | - [Built-in Functions](#built-in-functions)
13 |
14 | ---
15 |
16 | # Usage
17 | ~~Video tutorial available here: [Comet Tutorial](https://youtu.be/vzlmWR5MqCY)~~
18 | Currently unavailable — will be re-uploaded soon.
19 |
20 | ## Installation & Execution
21 | ### Using Pre-compiled Binary (Windows only)
22 | 1. Download `compiler.exe` from the [Release tab](https://github.com/alexmonkey05/Datapack-Compiler/releases).
23 | 2. There are two ways to run it:
24 | - Run `compiler.exe` directly → GUI mode.
25 | - Run `compiler.exe --cli ` → CLI mode.
26 |
27 | #### CLI Arguments
28 | | Argument | Description |
29 | | -------- | ----------- |
30 | | `--cli` | Enables CLI mode instead of GUI mode. |
31 | | `-p ` / `--planet` | Specifies the file to compile. |
32 | | `-v ` / `--version` | Minecraft version to compile for. |
33 | | `-d ` / `--dist` | Output folder for generated datapack. |
34 | | `-n ` / `--name` | Namespace name (default=`pack`). |
35 | | `-l` / `--logger` | Sets logging level (default=`INFO`). Levels: `DEBUG` > `INFO` > `WARNING` > `ERROR` > `CRITICAL` > `FATAL` > `LOG`. |
36 | | `-h` / `--help` | Displays help information. |
37 |
38 | #### CLI Example
39 | ```bash
40 | compiler.exe --cli --planet ./a.planet --version 1.21 --dist ./world/datapacks --name packpack --logger DEBUG
41 | ```
42 | ```bash
43 | compiler.exe --cli -p ./a.planet -v 1.21 -d ./world/datapacks -n packpack -l DEBUG
44 | ```
45 |
46 | ### Using Project Source Code (Windows, macOS, Linux)
47 | 1. Download the source code from the [Release tab](https://github.com/alexmonkey05/Datapack-Compiler/releases).
48 | 2. Navigate to the project directory:
49 | ```bash
50 | cd
51 | ```
52 | 3. Install dependencies:
53 | ```bash
54 | pip install -r requirements.txt
55 | ```
56 | **[Note]** On non-Windows systems, you may need:
57 | ```bash
58 | sudo apt-get install python3-tk
59 | ```
60 | 4. Run the compiler:
61 | ```bash
62 | python new_compiler.py # Windows
63 | python3 new_compiler.py # macOS/Linux
64 | ```
65 | This starts the GUI mode.
66 |
67 | ---
68 |
69 | ## GUI Mode
70 |
|
71 | :----: | :----:
72 | Compilation Success | Compilation Failure
73 |
74 | - Namespaces must be lowercase. Default=`pack`.
75 | - Click **Compile** to build the datapack.
76 | - Place the generated datapack and `basic_1.20.zip` or `basic_1.21.zip` inside your Minecraft world's `datapacks` folder.
77 | - For Minecraft `1.21.5+`, the basic datapack will **not** work.
78 | - Enter Minecraft and run `/reload` to apply changes.
79 |
80 | ---
81 |
82 | # VSCode Syntax Highlighting Extension
83 | [Comet Highlighter (VSC Marketplace)](https://marketplace.visualstudio.com/items?itemName=alexmonkey05.comet-highlighter)
84 |
85 | You can install it via the link above or by searching **Comet Highlighter** in VSCode Extensions.
86 | **Note:** This extension only provides syntax highlighting — **no autocomplete support**.
87 |
88 | ---
89 |
90 | # Contributing
91 | You can generate an executable using:
92 | ```bash
93 | pyinstaller --noconfirm --onefile --console --add-data "\grammer.lark;." --add-data "\web;web/" "\new_compiler.py"
94 | ```
95 | # 사용된 라이브러리 목록
96 | ```python
97 | import datetime
98 | from lark import Transformer, Token, Tree, Lark
99 | import os
100 | import json
101 | import shutil
102 | import sys
103 | import time
104 | ```
105 |
106 | ---
107 |
108 | # Grammar
109 | ## General
110 | ### Comments
111 | Use `#` to add comments:
112 | ```python
113 | # This is an awesome comment!
114 | ```
115 |
116 | ### Data Types
117 | - **int** → `1`, `-2`, `100`
118 | - **float, double** → `1.0`, `3.14`
119 | - Floats must include `f`, e.g. `1f`, `2.7f`.
120 | - **string** → `"This is string"`
121 | - **nbt** → Similar to JSON, e.g. `{id:"minecraft:block_display",Tags:["temp"]}`
122 |
123 | ### Variable Declaration
124 | ```python
125 | var a
126 | var b = 2.0
127 | var c = "asdf"
128 | var arr = [1, 2, 3]
129 | ```
130 |
131 | ### Local Variables
132 | Variables declared inside blocks are **scoped locally**.
133 | ```python
134 | var a
135 | if (condition) {
136 | var a
137 | }
138 | ```
139 |
140 | ### Newlines & Semicolons
141 | Statements can end with either `\n` or `;`.
142 | ```python
143 | var a
144 | var b = {
145 | test: "asdf"
146 | }
147 |
148 | var a;
149 | var b = {
150 | test: "asdf"
151 | };
152 | ```
153 |
154 | ### Minecraft Commands
155 | Commands starting with `/` are passed directly to Minecraft:
156 | ```python
157 | /say hello
158 | /gamemode creative @a
159 | ```
160 |
161 | ### Namespaces: `__namespace__` & `__main__`
162 | - `__namespace__` → Replaced with module path.
163 | - `__main__` → Always replaced with root namespace.
164 |
165 | ### Macros
166 | Use `$` for macros:
167 | ```python
168 | var a = 123
169 | /$say $(a)
170 | var cmd = "say hi"
171 | /$$(cmd)
172 | ```
173 |
174 | If you type `\$`, it will be changed to `$` when compiling.
175 | - Wrong example
176 | ```
177 | var a = 123
178 | /$say $(a) $
179 | ```
180 |
181 | ```
182 | lark.exceptions.UnexpectedToken: Unexpected token Token('__ANON_21', '$䗻\n') at line 2, column 12.
183 | Expected one of:
184 | * EOL
185 | * NO_DOLOR_WORD
186 | * ESCAPED_DOLOR
187 | * "$("
188 | * ESCAPED_MACRO
189 | Previous tokens: [Token('RPAR', ')')]
190 | ```
191 | - Correct example
192 | ```
193 | var a = 123
194 | /$say $(a) \$
195 | ```
196 |
197 | ```
198 | [@] 123 $
199 | ```
200 |
201 | In-game macros are also available, although they are a bit complicated.
202 | ```
203 | def foo(){
204 | /$\$say \$(text)
205 | }
206 | /function __namespace__:foo {text:"asdf"}
207 | ```
208 |
209 | ```
210 | [@] asdf
211 | ```
212 |
213 | ### Operators
214 | Order: **Parentheses > Member > Arithmetic > Relational > Logical > Assignment**
215 | - **Arithmetic:** `+`, `-`, `*`, `/`, `%`
216 | - **Relational:** `==`, `!=`, `<=`, `>=`, `<`, `>`
217 | - **Logical:** `and`, `or`, `!`
218 | - **Assignment:** `=`
219 |
220 | > ⚠️ **Note:** Arithmetic and relational operators do **not** work in Minecraft `1.21.5+`.
221 |
222 | ### Conditionals
223 | ```python
224 | if(a == 0){
225 | a = a + 1
226 | } else {
227 | a = a - 1
228 | }
229 | ```
230 | Supports `else if`, but using braces `{}` is recommended to avoid bugs.
231 |
232 | ### Loops
233 | ```python
234 | var a = 0
235 | while(a < 10){
236 | a = a + 1
237 | }
238 | ```
239 | Only `while` and `break` are supported. `for` and `continue` are **not** supported.
240 |
241 | ### Functions
242 | ```python
243 | def tick(){
244 | var a = 1
245 | }
246 |
247 | def test(var a, var b){
248 | print(a, b)
249 | }
250 | ```
251 |
252 | Special functions:
253 | - `def tick` → Runs in `#tick`.
254 | - `def load` → Runs in `#load`.
255 |
256 | ### Function Calls
257 | ```python
258 | def hello(){
259 | print("hi")
260 | }
261 | hello()
262 | ```
263 |
264 | ---
265 |
266 | ## import
267 | ```python
268 | import test
269 |
270 | test.print_test()
271 | ```
272 |
273 | ---
274 |
275 | ## execute
276 | Generally follows Minecraft syntax. Special case:
277 | ```python
278 | execute(if function {
279 | return 1
280 | } positioned 0 0 0){
281 | print("success!")
282 | }
283 | ```
284 |
285 | ---
286 |
287 | ## Built-in Functions
288 | | Function | Description |
289 | | -------- | ----------- |
290 | | `print(any ...)` | Prints values to chat. |
291 | | `random()` | Returns a random float between 0 and 1. |
292 | | `type(any)` | Returns the data type as a string. |
293 | | `round(float|double)` | Rounds a number to an integer. |
294 | | `get_score(player, objective)` | Gets a player's scoreboard value. |
295 | | `set_score(player, objective, value)` | Sets a scoreboard value. |
296 | | `get_data(from, name, dir)` | Reads NBT data. |
297 | | `set_data(from, name, dir, value)` | Writes NBT data. |
298 | | `append(arr, elem)` | Appends an element to an array. |
299 | | `del(var)` | Deletes variable or storage data. |
300 | | `len(var)` | Returns length of array or string. |
301 | | `is_module()` | Checks if file is imported as module. |
302 | | `divide(a, b)` | Divides two numbers with 5 decimal precision. |
303 | | `multiply(a, b)` | Multiplies two numbers with 5 decimal precision. |
304 | | `int(a)` | Converts to integer. |
305 | | `float(a)` | Converts to float. |
306 | | `double(a)` | Converts to double. |
307 | | `bool(a)` | Converts to boolean. |
308 | | `string(a)` | Converts to string. |
309 |
310 | ---
311 |
312 | This document is the English version of the project README. For detailed examples and updates, refer to the [official repository](https://github.com/alexmonkey05/Datapack-Compiler).
313 |
314 |
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Comet Compiler
6 |
7 |
8 |
9 |
10 |
11 |
15 |
16 |
70 |
71 |
225 |
226 |
227 |
--------------------------------------------------------------------------------
/log.md:
--------------------------------------------------------------------------------
1 | # 2024/05/15 1.0
2 | - 릴리즈
3 | # 2024/05/20 1.1
4 | - 한글이 깨지는 것 버그 고침
5 | - print에서 지역변수가 인식되던 버그 고침
6 | # 2024/05/31 2.0
7 | - 자료형이 더욱 유동적으로 변함
8 | - 변수 선언 키워드 변경
9 | - ("int", "float", "double", "string", "entity") -> var
10 | - 함수의 리턴 자료형 설정 불가능
11 | - get_data의 4번째 인자가 삭제됨
12 | - 3개의 인자만 받도록 변경됨
13 | # 2024/06/03 2.1
14 | - float(a)가 "data modify storage 40planet:value 1 set value a"로 컴파일 되던 오류 수정
15 | - A가 B를 import하고 B가 A를 import 했을 때 에러나는 현상 오류 수정
16 | # 2024/06/05 2.2
17 | - 버전 선택 기능 추가
18 | # 2024/06/06 2.3
19 | - 아래와 같은 상황에서 break, return이 정상작동 하지 않던 문제를 해결함
20 | ```
21 | def test(){
22 | execute(as @a){
23 | return 0
24 | }
25 | print("return dosen't worked")
26 | }
27 | ```
28 | # 2024/06/12 2.4
29 | - 아래와 같은 상황에서 break, return이 정상작동 하지 않던 문제를 해결함
30 | ```
31 | def test(){
32 | if(1 == 1){
33 | if(1 == 1){
34 | return 1
35 | print("asdf")
36 | }
37 | }
38 | }
39 | ```
40 | - 이중배열 선언 시 오류가 나던 문제를 해결함
41 | - `test.asdf.fdsa`와 같이 "." 연산자로 2번 이상 데이터 접근 시 오류가 나던 문제를 해결함
42 | # 2024/06/13 2.5
43 | - 함수를 정의하고 안에 아무것도 적지 않았을 경우 에러가 나던 문제를 해결함
44 | - `+` 연산으로 배열에 원소를 추가할 수 있음
45 | ```
46 | var arr = []
47 | arr = arr + 1
48 | ```
49 | - del 내장함수 추가
50 | - basic 데이터팩이 일부 변경 됨
51 | # 2024/06/15 2.6
52 | - 1.20 버전에서 `execute(if items)` 구문을 쓰면 에러가 나도록 바뀜
53 | - 1.21 버전을 선택할 수 있음
54 | # 2024/06/15 2.6.1
55 | - 1.20.4 버전에서 `execute(if items)` 구문을 쓰면 에러가 나도록 바뀜
56 | - 1.20.4, 1.20.6, 1.21 버전을 선택할 수 있음
57 | # 2024/06/15 2.6.2
58 | - `basic.zip` 내의 `functions` 폴더 명이 `function`로 수정됨
59 | - `basic.zip`이 버전에 따라 달라짐에 따라 `basic_1.20.zip`, `basic_1.21.zip`으로 나뉨
60 | - 내장함수 `string`에 변수를 넣었을 경우에 데이터팩에 오류가 나던 현상이 해결됨
61 | # 2024/06/15 2.7
62 | - `__namespace__`를 활용하여 마크 명령어를 입력할 때에 네임스페이스를 쓸 수 있게 됨
63 | ```
64 | def dumb_function(var a){
65 | return a
66 | }
67 |
68 | /function __namespace__:dumb_function
69 | ```
70 | # 2024/06/16 2.8
71 | - `+` 연산자로 원소를 추가할 수 없게 됨
72 | - `append` 내장함수가 추가됨
73 | `append(arr, element)`
74 | ```
75 | var arr = []
76 | append(arr, 1)
77 | var test = 2
78 | append(arr, test)
79 | print(arr)
80 | ```
81 | ```
82 | [1, 2]
83 | ```
84 | - `string` 내장함수가 제대로 작동하지 않던 오류를 해결함
85 | - `1.20.6`을 선택했을 때에 폴더명이 `function`으로 생성되던 오류를 해결함
86 | # 2024/06/17 2.8.1
87 | - `is_module()` 내장함수 추가
88 | ```
89 | if(is_module()){
90 | print("this is not main")
91 | }
92 | ```
93 | - `!` 안에 함수가 들어간 경우 에러가 나던 오류를 해결함
94 | - `!` 연산이 실질적으로 아무것도 수행하지 않던 오류를 해결함
95 | # 2024/06/17 2.8.2
96 | - 모듈 내의 변수에 접근할 수 없던 오류를 해결함
97 | - `break`, `return`을 감지하는 명령어가 중복되어 생성되는 오류를 해결함
98 | # 2024/06/17 2.9
99 | - 다차원 배열의 원소에 접근이 불가능하던 오류를 해결함
100 | # 2024/06/22 2.9.1
101 | - `.`연산자를 통해 변수의 요소에 접근 할 때 접근이 안 되던 오류를 해결함
102 | - `README.md`의 몇몇 오타 수정
103 | - `break`, `return`을 판단하는 변수가 초기화가 안 되던 오류를 해결함
104 | - `execute if` 구문에 `data` 추가
105 | # 2024/06/30 2.10
106 | - `del` 내장함수가 삭제된 값을 반환함
107 | - 함수의 인자가 제대로 전달되지 않던 오류를 수정함
108 | - `README.md`에 `del` 내장함수 설명을 적음
109 | - 몇몇 연산에 변수를 넣으면 제대로 작동하지 않던 오류를 해결함
110 | - `set_data`
111 | - 멤버연산 `[]`
112 | - `false`, `true` 추가
113 | - `len` 추가
114 | # 2024/07/10 2.10.1
115 | - `README.md` 영어로 변경
116 | - `README_kr.md` 추가
117 | - `README.md`의 `random` 내용 변경
118 | # 2024/07/16 2.10.2
119 | - `execute( if data var )` 형식에서 var에 점 연산이 있을 경우 에러가 나던 문제를 해결함
120 | - nbt 자료형의 키값에 문자열을 넣으면 에러가 나던 문제를 해결함
121 | - `3b`와 같은 `byte` 자료형을 `3`으로 컴파일 하던 에러를 해결함
122 | - print에 선택인자를 넣어도 선택된 엔티티가 출력되지 않던 에러를 해결함
123 | - `basic`의 논리 연산에서 값이 이상하게 나오던 에러를 해결함
124 | - 변수를 실행시키려 할 때, 에러가 나지 않던 것을 해결함
125 | ```
126 | var a = 1
127 | a()
128 | ```
129 | # 2024/07/16 2.11
130 | - 조건에 연산을 쓰지 않고 `while(var)`, `if(var)`의 형태로 적는 것이 가능해짐
131 | - `README.md`에 관련 내용 추가
132 | # 2024/07/17
133 | - `Comet Highlighter` 익스텐션 업데이트
134 | - `true`, `false` 키워드 추가
135 | - `unless` 키워드 추가
136 | # 2024/07/17 2.11.1
137 | - `break`를 사용했을 때 데이터팩이 고장나던 오류 수정
138 | - `while`의 조건에 변수를 넣었을 떼 2 이상인 경우에 반복이 안 되던 오류 수정
139 | - `return`이 2개 이상 있을 때 오류가 나던 현상 해결
140 | - `float`의 곱셈에서 수가 100배가 되던 현상 해결
141 | - `-`연산이 코드에 들어갈 경우 프로그램이 멈추던 오류 해결
142 | # 2024/07/23 2.11.2
143 | - 아래와 같이 `nbt`의 `value` 부분에 연산자 또는 배열을 넣을 경우 에러가 나던 현상 해결
144 | ```
145 | var test = {
146 | arr: [1, 2, 3],
147 | temp: 1b
148 | }
149 | var test2 = {
150 | test_arr: test.arr
151 | }
152 | ```
153 | - `.` 연산 이후에 멤버 접근 연산을 수행하려 할 때 에러가 나던 현상 해결
154 | ```
155 | var laundry = {
156 | arr: [1, 2, 3],
157 | temp: 1b
158 | }
159 |
160 | print(laundry.arr[0])
161 | print(laundry.arr[0].test)
162 | ```
163 | # 2024/08/05 2.11.3
164 | - `README`의 `execute if data` 부분의 오류 수정
165 | ```
166 | execute(if data storage "temp:test" id){
167 | ```
168 | ```
169 | execute(if data storage "temp:test" "id"){
170 | ```
171 | - nbt를 만들 때 빈 값(`{}`)이 들어가면 에러가 나던 현상 해결
172 | - nbt를 만들 때 `,`가 없을 때의 에러메시지 수정
173 | ```
174 | Invalid Syntax: : was not defined operator
175 | ```
176 | ```
177 | Invalid Syntax: prior "," is missing
178 | ```
179 | # 2024/08/08 2.11.4
180 | - `if`, `else` 등을 중괄호 없이 적었을 때 제대로 인식이 안 되던 오류 수정
181 | ```
182 | if(num == 1)
183 | print(1)
184 | else if(num == 2)
185 | print(2)
186 | else if(num == 3)
187 | print(3)
188 | else
189 | print("예측 실패")
190 | ```
191 | # 2024/08/16 2.12
192 | - `double` 내장함수가 작동하지 않던 오류 수정
193 | - 버전에 `1.21.1` 추가
194 | - 선택한 버전에 따라 `pack.mcmeta`의 버전이 바뀌도록 수정
195 | # 2024/08/23 2.13
196 | - `int`, `float`, `double`끼리의 연산이 가능해짐
197 | - `{}`로 묶인 부분이 파일의 마지막 글자일 때, 무한 로딩이 걸리던 버그를 해결함
198 | # 2024/08/31 2.14
199 | - `if block`이 문법을 제대로 지켜도 에러가 나던 현상을 해결함
200 | - `devide`, `multiply` 추가
201 | - 스토리지에 저장되는 정보에 네임스페이스를 추가함
202 | - ex) `pack_var_temp10`
203 | - 스토리지에 저장되는 경로가 data 아래로 옮겨짐
204 | - `execute` 구문 내의 모든 좌표는 문자열로 적어야 합니다
205 | ```
206 | execute(positioned 0 0 0){...}
207 | ```
208 | ```
209 | execute(positioned "0 0 0"){...}
210 | ```
211 | - `execute` 구문을 한 줄에 적을 필요가 없게 됨
212 | ```
213 | execute(as
214 | @a){
215 | /say a
216 | }
217 | ```
218 | - `execute` 구문의 `if function` 성능이 강화됨
219 | ```
220 | def test(){
221 | return 1
222 | }
223 |
224 | execute(if function {
225 | return test()
226 | }){
227 | print("성공!")
228 | }
229 | ```
230 | # 2024/09/24 2.14.1
231 | - `execute if score <플레이어> <스코어보드> matches`의 범위가 제대로 인식되지 않던 오류 수정
232 | - `execute if items`에서 아이템의 아이디 대신 `*`을 넣었을 경우, 에러가 나던 현상 해결
233 | - 함수의 `return`이 제대로 작동하지 않던 오류 해결
234 | - 실행 중 나오는 에러메시지에 `Runtime Error : ` 문구 추가
235 | - nbt와 배열을 생성할 때의 성능 개선
236 | # 2024/09/25 버전업 없음
237 | - `README.md`에 연산자의 자료형에 관한 내용 추가
238 | - 연산의 결과는 연산자의 뒤쪽 피연산자를 따라갑니다
239 | - ex) 0.3 * 1 = 0
240 | # 2024/09/30 버전업 없음
241 | - `README`에 `float`와 `double` 자료형의 경우엔 사칙연산에서 소수점 아래 3번째 자리부터 날라간다는 내용 추가
242 | - 몇몇 f format으로 쓰인 부분을 + 연산자로 바꿈
243 | - `README`에 혜성 1강 링크 추가
244 | # 2024/10/01 2.15
245 | - cli 추가 및 `README`에 관련 내용 추가
246 | # 2024/10/02 2.15.1
247 | - `var t = 2.5`와 같이 소수가 대입이 제대로 되지 않던 오류 수정
248 | - `devide` $\to$ `divide` 내장함수 이름 변경
249 | - 2024/10/02 oein님의 풀리퀘 merge
250 | - 정형화된 CLI 로그 추가
251 | - 에러 메시지, 실행 시 나오는 아이콘 등
252 | - 38번째 줄에 있는 `verboseLevel = LOGLEVEL["DEBUG"]`의 `"DEBUG"` 부분을 변경하여 로그에 표시될 내용을 변경할 수 있음
253 | # 2024/10/23 2.16
254 | - 모듈 내의 정의되지 않은 함수를 호출 할 때에 에러메시지가 안 뜨던 오류 수정
255 | - 아래와 같이 `if predicate`를 작성 시, 에러가 나는 현상 수정
256 | ```
257 | if predicate {"condition":"minecraft:entity_properties","entity":"this","predicate":{"vehicle":{}}}
258 | ```
259 | - 엔티티가 들어갈 자리에 이름을 직접 적거나 UUID를 작성한 경우에 에러를 내던 오류 수정
260 | - import 된 파일에서 다시 import 한 파일의 함수를 호출하는 경우, 호출이 안 되던 오류 수정
261 | - 반복문 안에서 return을 쓸 경우, 함수 탈출이 안 되던 오류 수정
262 | - 아래와 같이 `if block`을 작성 시, 에러가 나는 현상 발견
263 | ```
264 | if block "~ ~ ~" chest[facing=east]
265 | ```
266 | - `if items`에서 `weapon.offhand` 슬롯을 감지하려고 하면 에러가 나던 현상 수정
267 | - 선택 가능한 버전에 `1.21.2` 추가
268 | # 2024/11/24 2.16.1
269 | - tkinter 모듈의 `Variable`과 혜성의 `Variable`이 충돌하여 에러가 나던 현상 해결
270 | - `Variable` $\to$ `VariableComet`으로 클래스 명을 바꿔 해결
271 | # 2024/11/26 2.17
272 | - `del(a)`와 같이 del 함수에 변수를 넘겨줬을 경우 data remove 명령어가 제대로 작성되지 않던 오류 해결
273 | - 컴파일 할 때 데이터팩 전체를 지우고 새로 생성하는 것이 아닌, function 폴더만 지우고 새로 생성하는 것으로 바뀜
274 | - 입력한 네임스페이스 아래의 loot_table, recipe 등을 건드리지 않음
275 | # 2024/11/28
276 | ```
277 | var a = @p
278 | print(a)
279 | print(@p)
280 | ```
281 | - 위와 같은 코드를 컴파일 하면 두 print의 출력에 차이가 발생하는 문제를 인지함
282 | # 2024/12/27 3.0b
283 | - 포인터 추가
284 | - Lark를 이용해 내부 구조 리마스터
285 | - 이미 정의된 변수를 다시 정의하려 했을 때 에러가 발생하지 않게 됨
286 | - execute의 문법이 다수 개정됨
287 | - `"~ ~ ~"` $\to$ `~ ~ ~`
288 | - `if score "@s" "40planet_num"` $\to$ `if score @s 40planet_num`
289 | - 이 경우엔 전자도 가능하지만, 후자도 가능하도록 바뀜
290 | - 마인크래프트의 execute 명령어를 그대로 갖다 박아도 무사히 작동되도록 변경함
291 | - 매크로 문법이 변경됨
292 | - `/say ^variable&` $\to$ `/$say $(variable)`
293 | - 본래의 마크의 매크로 문법을 살림
294 | - 0b, 1b 등 마크 자료형 문제 해결
295 | - 엔티티 자료형 삭제
296 | ### 아직 정식으로 3.0을 릴리즈 한건 아님!
297 | # 2024/12/27
298 | - 늘 그렇듯 if, execute, while에서의 return, break 에러 수정
299 | # 2025/01/01
300 | - 3.0 베타 릴리즈
301 | - `{}`로 nbt를 생성할 때 오류가 나던 현상 해결
302 | - 창모드에서 컴파일이 불가능하던 에러 해결
303 | # 2025/01/06 3.0.1b
304 | - `/$$(a) $(b)`를 `$(a)$(b)`와 같이 컴파일하던 에러 해결
305 | - 함수의 매개변수로 넘어간 연산을 처리하지 않던 에러 해결
306 | - `multiply` 내장함수가 아예 작동하지 않던 에러 해결
307 | # 2025/01/10 3.0.2b
308 | - pyinstaller로 패키징 했을 때 abspath가 정상작동하지 않아 에러가 나던 현상 해결
309 | - `and`, `or`, `!` 연산 사용 시 에러나던 현상 해결
310 | - 빈 배열(`[]`) 선언 시 에러나던 현상 해결
311 | # 2025/01/13 3.0.3b
312 | - 아래와 같이 배열의 모든 원소에 대해 반복문을 돌리려고 할 때, 무한루프가 발생하는 오류 해결
313 | ```
314 | while(arr[0]){
315 | print(arr[0])
316 | del(arr[0])
317 | }
318 | ```
319 | - while 내부에서 break를 쓰면 while에서까지 break가 동작하는 오류 해결
320 | - 이전 실행의 break의 스코어보드가 이후 실행의 break에 영향을 끼치는 오류 해결
321 | - 대부분의 상황에서 논리연산자가 제대로 작동하지 않던 오류 해결
322 | # 2025/01/18 3.0.4b
323 | - `execute(as @a at @s) /$$(a)`와 같이 "/$"가 맨 처음에 오지 않을 때 매크로가 정상작동하지 않던 오류 해결
324 | - `item.components."minecraft:custom_data"`과 같이 `.`연산에서 문자열을 쓰고자 하면 에러가 나던 현상 해결
325 | - 배열에 음수인덱스 추가
326 | - 아래와 같은 상황에서 문자열을 정상적으로 인식하던 오류 해결
327 | ```
328 | a = "as
329 | df"
330 | ```
331 | - 매크로를 사용한 커맨드에서 `\$`로 "$"를 입력할 수 있는 기능이 추가됨
332 | # 2025/01/30 3.0.5b
333 | - `/$$(command)`와 같이 명령어의 처음부터 매크로를 사용하면 실행이 안 되던 에러 해결
334 | - 매크로를 컴파일하는 과정에서의 속도 향상
335 | # 2024/02/03 3.0
336 | - `del(data)`라는 코드가 있으면 인게임에서 많은 렉이 걸리고 튕기는 현상 해결
337 | - 배열을 만들 때 같은 배열을 두번 만드는 현상 해결
338 | # 2025/02/04 3.0.1
339 | - Linux 환경에서 `\`로 인한 경로 에러가 나던 것 수정
340 | - `README.md`에서 입문자가 읽기 더 편하게 바뀜
341 | - `README.md`, `README_kr.md` $\to$ `README_en.md`, `README.md`로 바뀜
342 | # 2025/02/19 3.1
343 | - -l 옵션으로 로그 레벨 조정 가능
344 | - DEBUG
345 | - INFO
346 | - WARNING
347 | - ERROR
348 | - CRITICAL
349 | - FATAL
350 | - LOG
351 | - 태그나 스코어보드 이름에 `.`이 들어가도 에러가 나지 않음
352 | - 명령어가 너무 길어지고 같은 변수를 반복해서 매크로로 사용할 경우 매크로가 정상작동하지 않는 오류 해결
353 | - 최적화를 진행, 내 노트북에선 약 3배 가량 빨라짐
354 | # 2025/03/14 3.1.1
355 | - 일부 마크 문법이 혜성에서 에러를 내던 오류 해결
356 | - `SelectedItem.components.minecraft:custom_data`
357 | - 아래와 같이 작성되면 nbt 데이터가 제대로 생성되지 않던 오류 해결
358 | ```
359 | {
360 | function: info.function,
361 | owner_id: get_score("@s", "40planet_id"),
362 | enabled: 1b
363 | }
364 | ```
365 | - 같은 .planet 파일을 서로 다른 파일에서 import 했을 때 에러가 나던 오류 해결
366 | # 2025/04/07 3.1.2, 3.1.3
367 | - `return`이 아예 작동하지 않던 오류 해결
368 | - `set_data`, `set_score`의 마지막 인수에 함수를 사용했을 때 함수가 두번씩 실행되던 오류 해결
369 | # 2025/04/14 3.2
370 | - import한 다른 파일의 전역변수에 접근 가능하게 됨
371 | # 2025/04/15 3.2.1, 3.2.2
372 | - `if block`의 문법오류 해결
373 | - block_state : `if block ~ ~ ~ stone_button[facing=north,face=floor,powered=false]`
374 | - nbt : `if block ~ ~ ~ barrel[open=true]{Items:[{Slot:26b,id:"minecraft:stone",count:1}]}`
375 | # 2025.05.18 3.2.3
376 | - `divide`에서 결과값이 항상 양수던 에러 해결
377 | # 2025.06.08 3.2.4
378 | - `if data storage fish {temp:"W"}`와 같이 if data 문법 추가
379 | # 2025.06.22 3.3
380 | - `1.21.5`, `1.21.6` 버전 추가
381 | - `1.21.5` 이상의 버전으로 컴파일을 했는데 basic 데이터팩에 의존하는 기능을 썼다면, 에러메시지 출력
382 | - 메인 `load.mcfunction`에 40planet_num 스코어보드를 추가하는 구문 추가
383 | # 2025.08.04 3.4 버전 추가
384 | - `1.21.7`, `1.21.8` 추가
385 | - `field[get_score("#x", "slot_num")] = get_data("entity", "@s", "item")`와 같이 접근하는 경우에 `data modify storage 40planet:value data.pack_temp18 set from entity @s item`와 같이 컴파일 되는 문제를 해결함
386 | - 변수를 쓰는 멤버 접근이 데이터팩에서 누락됨
387 | - `a.b = c`처럼 대입연산자 왼쪽에 멤버연산 혹은 `.`연산이 있는 경우 대입이 되지 않는 오류 해결
388 | # 2025.08.07 3.4.1
389 | - `load.mcfunction`에 `40planet_num` 스코어보드를 생성하는 구문과 `This data pack was compiled with the 40planet's compiler.` 문구가 누락되던 에러 해결
390 | # 2025.08.25 3.5 __main__ 추가
391 | - `__main__` 추가
392 | - import 된 파일에서도 네임스페이스로 바뀜
393 | - `__namespace__`는 `pack:test2/`와 같이 바뀌었다
394 | ```
395 | import test2
396 | /function __main__:test2/foo
397 | ```
398 | # 2025.09.04 3.6b 최적화
399 | - earley 파서에서 lalr 파서로 변경
400 | - 40배 정도의 성능 향상
401 | # 2025/09/06 3.6.1b
402 | - `if block`의 문법오류 해결
403 | - block_state : `if block ~ ~ ~ stone_button[facing=north,face=floor,powered=false]`
404 | - nbt : `if block ~ ~ ~ barrel[open=true]{Items:[{Slot:26b,id:"minecraft:stone",count:1}]}`
405 | - `armor.head`와 같이 아이템 슬롯 사이에 `.`이 들어가면 에러가 나던 현상 해결
406 | # 2025/09/07 3.6 정식 릴리즈
407 | - 테스트 케이스 모두 통과
408 | - `README.md` 수정
409 | # 2025/09/08 3.7 GUI 모드 기능 추가
410 | - GUI에서 마지막에 컴파일 한 값을 다시 켰을 때 기억한다
411 | # 2025/10/28 아직 릴리즈 안 함 3.7.1
412 | - `is_module()` 사용 시 에러가 나던 버그 수정
413 | - 라이센스 표시 추가
414 | - execute if block에서 properties, nbt 설정이 없는 경우 발생하던 에러 해결
--------------------------------------------------------------------------------
/grammer.lark:
--------------------------------------------------------------------------------
1 |
2 | // ==== LALR-friendly keyword tokens (added) ====
3 | IF_.50: "(" "if " | " if "
4 | AS_.50: "(" "as " | " as "
5 | UNLESS_.50: "(" "unless " | " unless "
6 | ROTATED_.50: "(" "rotated " | " rotated "
7 | POSITIONED_.50: "(" "positioned " | " positioned "
8 | IN_.50: "(" "in " | " in "
9 | ALIGN_.50: "(" "align " | " align "
10 | ANCHORED_.50: "(" "anchored " | " anchored "
11 | AT_.50: "(" "at " | " at "
12 | FACING_.50: "(" "facing " | " facing "
13 | ON_.50: "(" "on " | " on "
14 | STORE_.50: "(" "store " | " store "
15 | SUMMON_.50: "(" "summon " | " summon "
16 |
17 | // anchored
18 | EYES_.50: "eyes"
19 | FEET_.50: "feet"
20 |
21 | // over surface token (motion surfaces)
22 | OVER_.50: "over"
23 | MOTION_SURFACE.50: /(motion_blocking_no_leaves|motion_blocking|ocean_floor|world_surface)/
24 | POSITIONED_AS_.50: "as"
25 |
26 | // on-type (attacker/controller/...)
27 | ON_TYPE.50: /(attacker|controller|leasher|origin|owner|passengers|target|vehicle)/
28 |
29 | // store type
30 | STORE_TYPE.50: /(success|result)/
31 |
32 | // blocks mode
33 | BLOCKS_MODE.50: /(all|masked)/
34 |
35 | // -------------------- align 옵션 --------------------
36 | ALIGN_TYPE.50: /(xyz|xzy|yxz|yzx|zxy|zyx|xy|yx|xz|zx|yz|zy|x|y|z_)/
37 |
38 | // -------------------- anchored 옵션 --------------------
39 | ANCHORED_TYPE.50: /(eyes|feet)/
40 |
41 |
42 |
43 | // auto-generated simple keyword tokens
44 | PREDICATE_.50: "predicate"
45 | BIOME_.50: "biome"
46 | BLOCK_.50: "block"
47 | BLOCKS_.50: "blocks"
48 | DATA_.50: "data"
49 | DIMENSION_.50: "dimension"
50 | ENTITY_.50: "entity"
51 | FUNCTION_.50: "function"
52 | ITEMS_.50: "items"
53 | LOADED_.50: "loaded"
54 | SCORE_.50: "score"
55 | MATCHES_.50: "matches"
56 |
57 |
58 | // selector parameter
59 | SELECTOR_TAG.50: "tag="
60 | SELECTOR_ADVANCEMENTS.50: "advancements="
61 | SELECTOR_DISTANCE.50: "distance="
62 | SELECTOR_GAMEMODE.50: "gamemode="
63 | SELECTOR_LEVEL.50: "level="
64 | SELECTOR_LIMIT.50: "limit="
65 | SELECTOR_NAME.50: "name="
66 | SELECTOR_PREDICATE.50: "predicate="
67 | SELECTOR_SORT.50: "sort="
68 | SELECTOR_TEAM.50: "team="
69 | SELECTOR_TYPE.50: "type="
70 | SELECTOR_SCORES.50: "scores="
71 | SELECTOR_DX.50: /d[xyz]=/
72 | SELECTOR_X.50: /[xyz]=/
73 | SELECTOR_ROTATION.50: /[xy]_rotation=/
74 |
75 |
76 | ?score_operation: EQUAL | GE | LE | GT | LT
77 | GE: ">="
78 | LE: "<="
79 | GT: ">"
80 | LT: "<"
81 | EQUAL: "="
82 |
83 |
84 |
85 | //%import common.FLOAT
86 | FLOAT: /\d+\.\d+/
87 | //%import common.INT
88 | INT: /\d+/
89 | // %import common.ESCAPED_STRING
90 | ESCAPED_STRING: /"([^"\\\n]|\\.)*"/
91 | | /'([^'\\\n]|\\.)*'/
92 | // | /[a-zA-z]+/
93 | %import common.WS_INLINE
94 | %import common.WS
95 | // %import common.NEWLINE
96 |
97 |
98 | start: statement*
99 |
100 |
101 | ?statement: simple_statement | control_statement | declaration | condition
102 |
103 | ?simple_statement: minecraft_command | command_macro | variable_def | variable_set | eol
104 | ?control_statement: if_statement | while_statement | return_ | break_ | execute
105 | ?declaration: function_def | import_statement
106 |
107 |
108 | // minecraft_command: /\/[^\$][^\n]*/
109 | command_macro: "/$" ( ESCAPED_DOLOR | ESCAPED_MACRO | macro_ | NO_DOLOR_WORD )+ "䗻"
110 | minecraft_command.-1: "/" /[^䗻]+/ "䗻"
111 | // minecraft_command.10: "/" (macro | word)+ eol
112 | ESCAPED_DOLOR.100: "\$"
113 | ESCAPED_MACRO.100: ESCAPED_DOLOR "(" CNAME ")"
114 | macro_: "$(" CNAME ")"
115 | NO_DOLOR_WORD.-1: /(?:(?!\\\$)[^$\n䗻])+/
116 | // WORD: /[^\n䗻]+/
117 | // new_line.2: /\n/
118 | EOL: "䗻"
119 | // EOL: "䗻" | NEWLINE
120 | ?eol: ";" | EOL
121 |
122 | // 중괄호 블럭
123 | block: "{" statement* "}"
124 | | statement
125 |
126 | parameter_list: _seperated{parameter, ","}
127 | ?parameter: "var" CNAME
128 | arguments: _seperated{argument, ","}
129 | argument: condition
130 | | selector //-> selector
131 |
132 |
133 | // import문
134 | import_statement: "import" CNAME
135 |
136 | //멤버연산
137 | //--------------------------------------------------------------
138 | member_operation: variable "[" expression "]"
139 | | array "[" INT "]"
140 | | array "[" /[+-]\d+/ "]"
141 | dot_operation.30: dot_operation DOT ESCAPED_STRING
142 | | dot_operation DOT CNAME
143 | | CNAME DOT CNAME
144 | | variable DOT ESCAPED_STRING
145 | | variable DOT CNAME
146 | | dot_operation DOT no_dot_minecraft_id
147 | no_dot_minecraft_id : CNAME ":" CNAME
148 |
149 | //함수 선언, 실행
150 | //--------------------------------------------------------------
151 | function_def: "def" CNAME "(" [parameter_list] ")" block
152 | function_call: CNAME "(" [arguments] ")"
153 | method.-1: CNAME DOT CNAME "(" [arguments] ")"
154 |
155 |
156 |
157 | //변수 설정
158 | //--------------------------------------------------------------
159 | variable_def: "var" CNAME
160 | variable_set: CNAME set_value
161 | | variable set_value
162 | | variable_def set_value
163 | ?set_value : EQUAL condition
164 |
165 | //사칙연산
166 | //--------------------------------------------------------------
167 |
168 | // expression = 어떠한 값 (변수, 사칙연산 등)
169 | ?expression: expression "+" term -> add
170 | | expression "-" term -> sub
171 | | term
172 |
173 | ?term: term "*" factor -> mul
174 | // | term "/" factor -> div
175 | | term "%" factor -> mod
176 | | factor
177 |
178 | ?factor: value
179 | | "-" factor -> neg
180 | | "(" condition ")"
181 |
182 |
183 |
184 | //값 토큰 설정
185 | //--------------------------------------------------------------
186 | _seperated{x, sep}: (x (sep x)*)?
187 |
188 | ?variable.30: dot_operation
189 | | member_operation
190 | | CNAME
191 | | function_call
192 | | method
193 | // | pointer
194 | // | address
195 | // pointer: "*" "(" variable ")"
196 | // | "*" variable
197 | // address: "&" "(" variable ")"
198 | // | "&" variable -> address
199 |
200 | array.-9999: "[" _seperated{condition, ","} "]"
201 | nbt: "{" _seperated{pair, ","} "}"
202 | ?pair: CNAME ":" condition
203 | | ESCAPED_STRING ":" condition
204 |
205 | ?number: /-?\d+[bdf]?/
206 | | /-?\d+\.\d+[bdf]?/
207 | | /-?\.\d+[bdf]?/
208 | ?value: ESCAPED_STRING
209 | | variable
210 | | FLOAT
211 | | INT
212 | | array
213 | | nbt
214 | | number
215 |
216 |
217 | //키워드 설정
218 | //--------------------------------------------------------------
219 | return_: "return" condition
220 | break_.10: "break"
221 |
222 | //조건문, 반복문 설정
223 | //--------------------------------------------------------------
224 | if_statement: "if" "(" condition ")" block ("else" block)?
225 | while_statement: "while" "(" condition ")" block
226 |
227 |
228 | //논리연산
229 | //--------------------------------------------------------------
230 | ?logic_operation : expression
231 | | expression "==" expression -> equal
232 | | expression ">" expression -> bigger
233 | | expression ">=" expression -> bigger_equal
234 | | expression "<" expression -> smaller
235 | | expression "<=" expression -> smaller_equal
236 | | expression "!=" expression -> not_equal
237 | | "!" "(" logic_operation ")" -> not_operation
238 | ?condition: logic_operation
239 | | condition "and" condition -> and_operation
240 | | condition "or" condition -> or_operation
241 |
242 |
243 | // execute 설정
244 | //--------------------------------------------------------------
245 | MINECRAFT_NUMBER.101: /-?\.\d+/
246 | | /-?\d+\.\d+/
247 | | /-?\d+/
248 | MINECRAFT_RANGE: MINECRAFT_NUMBER
249 | | MINECRAFT_NUMBER TWO_DOT
250 | | TWO_DOT MINECRAFT_NUMBER
251 | | MINECRAFT_NUMBER TWO_DOT MINECRAFT_NUMBER
252 | TWO_DOT: ".."
253 | ?minecraft_id: minecraft_name ":" minecraft_name
254 | | minecraft_name
255 | ?minecraft_id_tag: "#" minecraft_id
256 | | minecraft_id
257 | ?json_pair: ESCAPED_STRING ":" json_value
258 | ?json_value: ESCAPED_STRING
259 | | number
260 | | "true"
261 | | "false"
262 | | "{" _seperated{json_pair, ","} "}" -> json_
263 |
264 | ?selector: /@[parsen]/ ("[" _seperated{selector_parameter, ","} "]")?
265 | | UUID
266 | UUID: /"?[a-z\d]+-[a-z\d]+-[a-z\d]+-[a-z\d]+-[a-z\d]+"?/
267 | selector_parameter: SELECTOR_TAG (/!/? minecraft_name)?
268 | | SELECTOR_ADVANCEMENTS minecraft_id_tag
269 | | SELECTOR_DISTANCE MINECRAFT_RANGE
270 | | SELECTOR_DX INT
271 | | SELECTOR_GAMEMODE /!?(?:adventure|creative|survival|spectator)/
272 | | SELECTOR_LEVEL MINECRAFT_RANGE
273 | | SELECTOR_LIMIT INT
274 | | SELECTOR_NAME /!/? minecraft_name
275 | // | "nbt=" /!/? nbt -> selector_nbt
276 | | SELECTOR_PREDICATE minecraft_id
277 | | SELECTOR_SCORES "{" (minecraft_name EQUAL MINECRAFT_RANGE)? ("," minecraft_name EQUAL MINECRAFT_RANGE)* "}" -> scores
278 | | SELECTOR_SORT /(arbitrary|furthest|nearest|random)/
279 | | SELECTOR_TEAM minecraft_name
280 | | SELECTOR_X MINECRAFT_NUMBER
281 | | SELECTOR_ROTATION MINECRAFT_RANGE
282 | | SELECTOR_TYPE /!/? minecraft_id_tag
283 |
284 |
285 |
286 | ?coordinate_set: coord coord coord
287 | | face_angle face_angle face_angle
288 | face_angle: /\^([+-]?(\d+(\.\d+)?|\.\d+))?/
289 | ?coord: /~([+-]?(\d+(\.\d+)?|\.\d+))?/
290 | | MINECRAFT_NUMBER
291 |
292 | execute: "execute" execute_parameter+ ")" block
293 | execute_parameter: AS_ selector
294 | | IF_ execute_if
295 | | UNLESS_ execute_if
296 | | POSITIONED_ execute_positioned
297 | | IN_ minecraft_id_tag
298 | | ALIGN_ ALIGN_TYPE
299 | | ANCHORED_ ANCHORED_TYPE
300 | | AT_ selector
301 | | FACING_ execute_facing
302 | | ON_ ON_TYPE
303 | | ROTATED_ execute_rotated
304 | | STORE_ STORE_TYPE execute_store
305 | | SUMMON_ minecraft_id
306 |
307 |
308 |
309 |
310 | ?execute_positioned: coordinate_set
311 | | OVER_ /(motion_blocking_no_leaves|motion_blocking|ocean_floor|world_surface)/
312 | | POSITIONED_AS_ selector
313 | ?execute_rotated: coord coord
314 | | POSITIONED_AS_ selector
315 |
316 | ?execute_facing: coordinate_set
317 | | ENTITY_ selector ANCHORED_TYPE
318 |
319 | ?nbt_dir: MINECRAFT_NAME_NOT_DOT
320 | | ESCAPED_STRING
321 | | nbt_dir /\[[+-]?\d+\]/
322 | | nbt_dir /\./ (MINECRAFT_NAME_NOT_DOT | ESCAPED_STRING)
323 | ?execute_store: execute_store_list nbt_dir /(byte|double|float|int|long|short)/ MINECRAFT_NUMBER
324 | | SCORE_ (selector|minecraft_name) minecraft_name
325 | ?execute_store_list: block_entity
326 | | BOSSBAR_ minecraft_id
327 | | SCORE_ (selector|minecraft_name) minecraft_name
328 | | STORAGE_ minecraft_id
329 | BOSSBAR_.50:"bossbar"
330 | STORAGE_.50:"storage"
331 |
332 | nbt_pair: "{" _seperated{pair, ","} "}"
333 | // -------------------- execute_if --------------------
334 | ?execute_if: PREDICATE_ execute_if_predicate
335 | | BIOME_ coordinate_set minecraft_id_tag
336 | | BLOCK_ coordinate_set execute_if_block
337 | | BLOCKS_ coordinate_set coordinate_set coordinate_set /(all|masked)/
338 | | DATA_ execute_if_data (nbt_dir|nbt_pair)
339 | | DIMENSION_ minecraft_id_tag
340 | | ENTITY_ selector
341 | | FUNCTION_ execute_if_function
342 | | ITEMS_ block_entity item_slot item
343 | | LOADED_ coordinate_set
344 | | SCORE_ scoreboard execute_if_score
345 |
346 | // -------------------- 키워드 토큰 --------------------
347 | CONTENTS_.50: "contents"
348 | WEAPON_.50: "weapon"
349 | WEAPON_OPTION.50: "mainhand" | "offhand"
350 | PLAYER_CURSOR_.50: "player.cursor"
351 |
352 | ?execute_if_predicate: "{" _seperated{json_pair, ","} "}"
353 | | minecraft_id
354 | ?execute_if_data: block_entity
355 | | STORAGE_ minecraft_id
356 | execute_if_function: minecraft_id_tag
357 | | if_function_block
358 | if_function_block: "{" statement* "}"
359 | ?block_entity: BLOCK_ coordinate_set
360 | | ENTITY_ selector
361 | ?item_slot: /(container|enderchest|horse|hotbar|inventory|player\.crafting|villager)\.(\d+|\*)/
362 | | CONTENTS_
363 | | WEAPON_ DOT WEAPON_OPTION
364 | | WEAPON_
365 | | HORSE_ DOT /(?:chest|saddle)/
366 | | ARMOR_ DOT /(?:\*|body|chest|feet|head|legs)/
367 | | PLAYER_CURSOR_
368 | ARMOR_: "armor"
369 | HORSE_: "horse"
370 | item: (/\*/ | minecraft_id_tag) ("[" /[^\]]+/ "]")?
371 | // COMPONENTS: "[" /[^\]]*/ "]"
372 | ?execute_if_score: MATCHES_ MINECRAFT_RANGE
373 | | score_operation scoreboard
374 | ?scoreboard: (selector|ESCAPED_STRING|minecraft_name) (ESCAPED_STRING|minecraft_name)
375 | // execute if block ~ ~ ~ stone_button[facing=north,face=floor,powered=false]
376 | // execute if block ~ ~ ~ barrel[open=true]{Items:[{Slot:0b,id:"minecraft:stone",Count:1b}]}
377 | // 이런거 감지하는거
378 | ?block_state_pair: CNAME EQUAL CNAME
379 | // block_state.50: "[" _seperated{block_state_pair, ","} "]"
380 | execute_if_block: minecraft_id_tag ("[" _seperated{block_state_pair, ","} "]")? (nbt_pair)?
381 |
382 |
383 | // TODO : class 설정
384 | //--------------------------------------------------------------
385 | // class_def: "class" CNAME "{" ((function_def | variable_def) eol?)* "}"
386 | // method: variable DOT CNAME "(" [arguments] ")"
387 |
388 |
389 |
390 | // %ignore WS_INLINE
391 | %ignore WS
392 | %ignore /#[^\n;]*/ // 주석
393 | // %ignore /\n/
394 | // %ignore NEWLINE
395 |
396 |
397 | MINECRAFT_NAME_NOT_DOT: /[a-zA-Z0-9_]+/
398 | ?minecraft_name: MINECRAFT_NAME_NOT_DOT (DOT MINECRAFT_NAME_NOT_DOT)*
399 |
400 | // MINECRAFT_NAME_NOT_DOT: /[a-zA-Z0-9_]+/
401 | // minecraft_name.-1: MINECRAFT_NAME_NOT_DOT | /[a-zA-Z0-9_.]+/
402 |
403 |
404 |
405 | // Helper for dotted member access (accept CNAME or ESCAPED_STRING as name)
406 | DOT: "."
407 | NAME: CNAME | ESCAPED_STRING
408 |
409 | member_access: NAME ( "[" INT "]" )* ( DOT NAME ( "[" INT "]" )* )*
410 |
411 |
412 | // %import common.CNAME
413 | CNAME: /[A-Za-z_][A-Za-z0-9_]*/
--------------------------------------------------------------------------------
/new_compiler.py:
--------------------------------------------------------------------------------
1 | from logger import L, LOGLEVEL
2 | import os
3 | import shutil
4 | from transform import DatapackGenerater, error_as_txt, modify_file_data, filedata
5 | from consts import planet_parser, NEW_LINE
6 | import datetime
7 | import sys
8 |
9 |
10 | logger = L()
11 | COMET_CACHE_FILE = "./comet_cache.txt"
12 | existing_functions = {}
13 |
14 |
15 | datapack_versions = {
16 | "1.20.4": "26",
17 | "1.20.6": "41",
18 | "1.21": "48",
19 | "1.21.1": "48",
20 | "1.21.2": "57",
21 | "1.21.3": "57",
22 | "1.21.4": "61",
23 | "1.21.5": "71",
24 | "1.21.6": "71",
25 | "1.21.7": "80",
26 | "1.21.8": "80"
27 | }
28 |
29 | def search_functions(function_folder_dir):
30 | global existing_functions
31 | if not os.path.exists(function_folder_dir):
32 | existing_functions = {}
33 | return
34 | filenames = os.listdir(function_folder_dir)
35 | for filename in filenames:
36 | if filename == "tick.mcfunction" or filename == "load.mcfunction": continue
37 | full_filename = os.path.join(function_folder_dir, filename)
38 | full_filename = full_filename.replace("\\", "/")
39 | if filename.split(".")[-1] != "mcfunction": search_functions(full_filename)
40 | else: existing_functions[full_filename] = True
41 | # 네임스페이스/functions, tick.json, load.json 삭제 후 재생성
42 | def make_basic_files(version, file_dir, namespace = "pack"):
43 | logger.debug("make_basic_files", f"version: {version}, file_dir: {file_dir}, namespace: {namespace}")
44 |
45 | function_folder = "function"
46 | if version[:4] == "1.20": function_folder = "functions"
47 |
48 | function_folder_dir = os.path.join(file_dir, namespace, "data", namespace, function_folder)
49 | tag_folder_dir = os.path.join(file_dir, namespace, "data", "minecraft", "tags", function_folder)
50 |
51 |
52 | # if os.path.exists(file_dir + f"{namespace}/data/{namespace}/{function_folder}"): shutil.rmtree(file_dir + f"{namespace}/data/{namespace}/{function_folder}")
53 | search_functions(function_folder_dir)
54 | if os.path.exists(function_folder_dir): shutil.rmtree(function_folder_dir)
55 |
56 |
57 | if not os.path.exists(tag_folder_dir): os.makedirs(tag_folder_dir)
58 | if not os.path.exists(function_folder_dir): os.makedirs(function_folder_dir)
59 |
60 | load_json = file_dir + f"{namespace}/data/minecraft/tags/{function_folder}/load.json"
61 | tick_json = file_dir + f"{namespace}/data/minecraft/tags/{function_folder}/tick.json"
62 | load_mcfunction = file_dir + f"{namespace}/data/{namespace}/{function_folder}/load.mcfunction"
63 | tick_mcfunction = file_dir + f"{namespace}/data/{namespace}/{function_folder}/tick.mcfunction"
64 | pack_mcmeta = file_dir + f"{namespace}/pack.mcmeta"
65 | file = open(load_json, "w+")
66 | file.write(f"{{\"values\": [\"{namespace}:load\"]}}")
67 | file.close()
68 | file = open(tick_json, "w+")
69 | file.write(f"{{\"values\": [\"{namespace}:tick\"]}}")
70 | file.close()
71 | if not os.path.isfile(load_mcfunction):
72 | file = open(load_mcfunction, "w+")
73 | file.write(f"\
74 | # This data pack was compiled with the 40planet's compiler.\n\
75 | # https://github.com/alexmonkey05/Datapack-Compiler\n\nscoreboard objectives add 40planet_num dummy\n")
76 | file.close()
77 | if not os.path.isfile(tick_mcfunction):
78 | file = open(tick_mcfunction, "w+")
79 | file.close()
80 | if not os.path.isfile(pack_mcmeta):
81 | file = open(pack_mcmeta, "w+")
82 | file.write('{ "pack": {"pack_format": ' + datapack_versions[version] + ', "description": "by 40planet"} }')
83 | file.close()
84 |
85 |
86 | def generate_datapack(filename, version, result_dir = "./", namespace = "pack"):
87 | # 파일 경로 가공
88 | result_dir = result_dir.strip()
89 | namespace = namespace.strip()
90 | if result_dir == "" or namespace == "":
91 | logger.critical("\n\nresult directory and namespace can not be empty string\n")
92 | return
93 | if result_dir[-1] != "/" and result_dir[-1] != "\\":
94 | result_dir += "/"
95 |
96 | # 데이터팩 기본 경로 만들기
97 | make_basic_files(version, result_dir, namespace)
98 |
99 | # 파일 경로 가공
100 | if len(filename) < 7 or filename[-7:] != ".planet": filename += ".planet"
101 |
102 | # .planet 파일 존재 확인
103 | if not os.path.isfile(filename):
104 | raise ValueError(error_as_txt(None, f"\"{filename}\" does not exist", filename, "", "fdsa"))
105 |
106 |
107 | # 파싱
108 | now = datetime.datetime.now()
109 | parser_tree = None
110 | with open(filename, "r", encoding="utf-8") as file:
111 | logger.debug("open_file", f"{logger.fit(filename, 20)} took {logger.prYello(int((datetime.datetime.now() - now).total_seconds() * 1000) / 1000)}s")
112 |
113 | now = datetime.datetime.now()
114 | file_data = modify_file_data(file.read())
115 |
116 | parser_tree = planet_parser.parse(file_data + "\n")
117 | logger.debug("parse_file",f"{logger.fit(filename, 20)} took {logger.prYello(int((datetime.datetime.now() - now).total_seconds() * 1000) / 1000)}s")
118 |
119 | # make_basic_files("1.21", "./", "pack")
120 |
121 | # 트랜스폼
122 | now = datetime.datetime.now()
123 | # print(parser_tree.pretty())
124 | datapack_generator = DatapackGenerater(version, result_dir, namespace, filename, logger_level=logger)
125 | datapack_generator.transform(parser_tree)
126 | logger.debug("interprete_file", f"{logger.fit(filename, 20)} took {logger.prYello(int((datetime.datetime.now() - now).total_seconds() * 1000) / 1000)}s")
127 | write_all_files()
128 | return parser_tree
129 |
130 | def write_all_files():
131 | now = datetime.datetime.now()
132 | for filename in filedata:
133 | if filename in existing_functions: del existing_functions[filename]
134 | # if filename in comet_cache and filedata[filename] == comet_cache[filename]: continue
135 | with open(filename, "a+", encoding="utf-8") as file:
136 | file.write(filedata[filename])
137 | # with open(COMET_CACHE_FILE, "w+", encoding="utf-8") as file:
138 | # file.write(str(filedata))
139 | # for filename in existing_functions:
140 | # os.remove(filename)
141 | logger.debug("write_datapack", f"Took {logger.prYello(int((datetime.datetime.now() - now).total_seconds() * 1000) / 1000)}s")
142 |
143 | import argparse
144 | values = ["1.20.4", "1.20.6", "1.21", "1.21.1", "1.21.2", "1.21.3", "1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8"]
145 | if __name__ == "__main__":
146 |
147 | # if os.path.isfile(COMET_CACHE_FILE):
148 | # with open(COMET_CACHE_FILE, "r+", encoding="utf-8") as file:
149 | # comet_cache = eval(file.read())
150 | # else:
151 | # comet_cache = {}
152 |
153 | parser = argparse.ArgumentParser(
154 | prog='comet_compiler',
155 | description='Compile .planet files')
156 | parser.add_argument('--cli', action='store_true', help="Use cli instead of gui") # option that takes a value
157 | parser.add_argument('-p', '--planet', help="Select file to compile")
158 | parser.add_argument('-v', '--version', help="Select minecraft version")
159 | parser.add_argument('-d', '--dist', help="Select folder to locate output")
160 | parser.add_argument('-n', '--name', help="Input namespace. Default value is \"pack\".")
161 | parser.add_argument('-l', '--logger', help="Input logger level. Default value is \"INFO\".")
162 | args = parser.parse_args()
163 | if args.cli:
164 | logger.log("===============================================")
165 | logger.log(" ██████╗ ██████╗ ███╗ ███╗███████╗████████╗ ")
166 | logger.log(" ██╔════╝██╔═══██╗████╗ ████║██╔════╝╚══██╔══╝ ")
167 | logger.log(" ██║ ██║ ██║██╔████╔██║█████╗ ██║ ")
168 | logger.log(" ██║ ██║ ██║██║╚██╔╝██║██╔══╝ ██║ ")
169 | logger.log(" ╚██████╗╚██████╔╝██║ ╚═╝ ██║███████╗ ██║ ")
170 | logger.log(" ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ")
171 | logger.log("===============================================")
172 |
173 | now = datetime.datetime.now()
174 |
175 | v = args.version
176 | if v not in values or v == "":
177 | logger.critical(f"Invalid version: {v} / Required version: {values}")
178 | sys.exit(0)
179 | p = args.planet
180 | d = args.dist
181 | if p == None:
182 | logger.critical("planet file(-p / --planet) is required")
183 | sys.exit(0)
184 | if d == None:
185 | logger.critical("dist folder(-d / --dist) is required")
186 | sys.exit(0)
187 | n = args.name
188 | if n == None:
189 | n = "pack"
190 | logger.info("namespace", f"namespace is not defined, using default namespace: {logger.prGreen(n)}")
191 | l = args.logger
192 | if l == None: l = "INFO"
193 | logger.verboseLevel = LOGLEVEL[l]
194 |
195 |
196 | try:
197 | interprete_result = generate_datapack(p, v, d, n)
198 | except ValueError as err:
199 | print(err)
200 | sys.exit()
201 | logger.critical(err)
202 | took = int((datetime.datetime.now() - now).total_seconds() * 1000) / 1000
203 | logger.log(f"Done! Took {logger.prYello(took)}s")
204 |
205 |
206 | sys.exit(0)
207 |
208 | import eel
209 | import tkinter
210 | import json
211 | from tkinter import filedialog
212 | from eel import chrome, edge
213 |
214 | CONFIG_FILE = "./settings.json"
215 |
216 | @eel.expose
217 | def load_settings():
218 | if os.path.exists(CONFIG_FILE):
219 | with open(CONFIG_FILE, "r", encoding="utf-8") as f:
220 | return json.load(f)
221 | else:
222 | default_settings = {
223 | "file": "",
224 | "folder": "",
225 | "namespace": "pack"
226 | }
227 | save_settings(default_settings)
228 | return default_settings
229 |
230 | @eel.expose
231 | def save_settings(settings):
232 | with open(CONFIG_FILE, "w", encoding="utf-8") as f:
233 | json.dump(settings, f, indent=4, ensure_ascii=False)
234 |
235 | parentDir = os.path.dirname(__file__)
236 |
237 | eel.init(os.path.join(parentDir, "web"));
238 |
239 | @eel.expose
240 | def event(name, dir, version, namespace):
241 | try:
242 | generate_datapack(name, version, dir, namespace)
243 | return "success"
244 | except BaseException as error:
245 | logger.critical(str(error));
246 | return str(error)
247 |
248 |
249 | @eel.expose
250 | def select_planet_file():
251 | root = tkinter.Tk()
252 | root.attributes("-topmost", True)
253 | root.withdraw()
254 | result = filedialog.askopenfile(
255 | title="파일 선택창",
256 | filetypes=(('planet files', '*.planet'), ('all files', '*.*'))
257 | )
258 | if result:
259 | return result.name
260 | else:
261 | return ""
262 |
263 | @eel.expose
264 | def select_folder():
265 | root = tkinter.Tk()
266 | root.attributes("-topmost", True)
267 | root.withdraw()
268 | directory_path = filedialog.askdirectory()
269 | return directory_path
270 |
271 |
272 | import webbrowser
273 | @eel.expose
274 | def open_folder(path):
275 | webbrowser.open(f"file:///{path}")
276 |
277 | def __can_use_chrome():
278 | """Identify if Chrome is available for Eel to use"""
279 | chrome_instance_path = chrome.find_path()
280 | return chrome_instance_path is not None and os.path.exists(chrome_instance_path)
281 |
282 |
283 | def __can_use_edge():
284 | """Identify if Edge is available for Eel to use"""
285 | return edge.find_path()
286 |
287 | import socket
288 |
289 | def get_port():
290 | """Get an available port by starting a new server, stopping and and returning the port"""
291 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
292 | sock.bind(("localhost", 0))
293 | port = sock.getsockname()[1]
294 | sock.close()
295 | return port
296 |
297 | class UIOpenMode:
298 | NONE = 0
299 | CHROME_OR_EDGE = 1
300 | DEFAULT_BROWSER = 2
301 |
302 | # try:
303 | chrome_available = __can_use_chrome()
304 | edge_available = __can_use_edge()
305 | open_mode = UIOpenMode.CHROME_OR_EDGE
306 |
307 | if open_mode == UIOpenMode.CHROME_OR_EDGE and chrome_available:
308 | logger.info("The interface is being opened in a new Chrome window")
309 | logger.info(
310 | "Please do not close this terminal while using this compiler - the process will end when the window is closed"
311 | )
312 | eel.start("index.html", size=(600, 800), port=0, mode="chrome")
313 | elif open_mode == UIOpenMode.CHROME_OR_EDGE and edge_available:
314 | logger.info("The interface is being opened in a new Edge window")
315 | logger.info(
316 | "Please do not close this terminal while using this compiler - the process will end when the window is closed"
317 | )
318 | eel.start("index.html", size=(600, 800), port=0, mode="edge")
319 | elif open_mode == UIOpenMode.DEFAULT_BROWSER or (
320 | open_mode == UIOpenMode.CHROME_OR_EDGE and not chrome_available and not edge_available
321 | ):
322 | logger.info("The interface is being opened in your default browser")
323 | logger.info(
324 | "Please do not close this terminal while using this compiler - the process will end when the window is closed"
325 | )
326 | eel.start("index.html", size=(600, 800), port=0, mode="user default")
327 | else:
328 | port = get_port()
329 | logger.info(f"Server starting at http://localhost:{port}/index.html")
330 | logger.info("You may end this process using Ctrl+C when finished using auto-py-to-exe")
331 | eel.start("index.html", host="localhost", port=port, mode=None, close_callback=lambda x, y: None)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Datapack-Compiler
2 | 이 프로젝트는 마인크래프트 컴파일러를 만드는 프로젝트입니다.
3 | 가독성 향상과 if, while 등 일반적인 프로그래밍 언어의 기능을 구현하는 것에 중점을 두고 있습니다.
4 | 40행성(40planet)에 의해 제작되었으며, 출처만 표기한다면 자유로운 사용을 허가합니다.
5 | MIT 라이센스를 따릅니다
6 |
7 | If you are english speaker, check out [README_en.md](https://github.com/alexmonkey05/Datapack-Compiler/blob/main/README_en.md)!
8 |
9 | - [사용법](#사용법)
10 | - [Vscode 문법 강조 확장](#vscode-문법-강조-확장)
11 | - [기여](#기여)
12 | - [문법](#문법)
13 | - [일반](#일반)
14 | - [execute](#execute)
15 | - [import](#import)
16 | - [내장 함수](#내장-함수)
17 |
18 | # 사용법
19 | ~~영상 튜토리얼이 있습니다! [Comet Tutorial](https://youtu.be/vzlmWR5MqCY)을 참고하세요.~~
20 | 현재 영상이 소실되었습니다. 빠른 시일 내에 업로드 하겠습니다.
21 |
22 | ## 설치 및 실행
23 | ### 컴파일 버전 사용 (Windows 한정)
24 | 1. [Release 탭](https://github.com/alexmonkey05/Datapack-Compiler/releases)에서 `compiler.exe`를 다운로드합니다.
25 | 1. 실행에는 두 가지 방법이 있습니다. `compiler.exe`를 실행할 경우, GUI 모드로 진입하며, `compiler.exe --cli `를 입력해 실행할 경우, CLI 모드로 진입합니다.
26 |
27 | #### 인자 (CLI 모드)
28 | | 인자 | 설명 |
29 | | ---- | ---- |
30 | | `--cli` | GUI 모드 대신 CLI 모드를 사용합니다. |
31 | | `-p ` or `--planet` | 컴파일 할 파일을 지정합니다. |
32 | | `-v ` or `--version` | 컴파일에 사용할 마인크래프트 버전을 지정합니다. |
33 | | `-d ` or `--dist` | 결과물이 위치할 폴더를 지정합니다. |
34 | | `-n ` or `--name` | 네임스페이스를 입력합니다. (기본값=`pack`) |
35 | | `-l` or `--logger` | 출력될 로그의 레벨을 정합니다. (기본값=`INFO`) (`DEBUG` > `INFO` > `WARNING` > `ERROR` > `CRITICAL` > `FATAL` > `LOG` 순으로 레벨이 높습니다.) |
36 | | `-h` or `--help` | 도움말 페이지를 표시합니다. |
37 |
38 | #### 예제 (CLI 모드)
39 | ```
40 | compiler.exe --cli --planet ./a.planet --version 1.21 --dist ./world/datapacks --name packpack --logger DEBUG
41 | ```
42 | ```
43 | compiler.exe --cli -p ./a.planet -v 1.21 -d ./world/datapacks -n packpack -l DEBUG
44 | ```
45 |
46 | ### 프로젝트 코드 사용 (Windows, macOS, Linux)
47 | 1. [Release 탭](https://github.com/alexmonkey05/Datapack-Compiler/releases)에서 프로젝트 코드를 다운로드합니다.
48 | 1. `cd <프로젝트 경로>`를 실행합니다.
49 | 1. `pip install -r requirements.txt`를 실행합니다. 이 작업은 필요한 패키지를 자동으로 설치합니다.\
50 | **[Warning]** 만약, Windows 유저가 아닐경우, `sudo apt-get install python3-tk` 명령어를 입력해야 할 수도 있습니다.
51 | 1. `python new_compiler.py`(Windows) 또는 `python3 new_compiler.py`(유니버설)를 실행합니다. 실행 시 GUI 모드로 진입합니다.
52 |
53 | ## GUI 모드
54 |
|
55 | :----: | :----:
56 | 컴파일 성공 시 | 컴파일 실패 시
57 |
58 | - 네임스페이스는 소문자만 입력받습니다. 기본값은 `pack`입니다.
59 | - `컴파일` 버튼을 눌러 코드를 컴파일합니다.
60 | - 마인크래프트 세이브파일의 `datapacks` 폴더에 생성된 데이터팩과 `basic_1.20.zip` 또는 `basic_1.21.zip`을 넣어줍니다.
61 | - 마인크래프트 버전 `1.21.5` 이상에선 basic 데이터팩이 작동하지 않습니다
62 | - 이제 마인크래프트에 접속해 `/reload`를 실행해 데이터팩을 새로고침하면 실행됩니다.
63 |
64 | # Vscode 문법 강조 확장
65 | [Comet Highlighter(VSC Marketplace Link)](https://marketplace.visualstudio.com/items?itemName=alexmonkey05.comet-highlighter)
66 | 위의 링크로 들어가거나 VSCode를 실행 후 extensions에서 Comet Highlighter를 검색해 다운로드 하여 사용할 수 있습니다
67 | 해당 익스텐션은 색만 표시해줄 뿐, 자동완성 기능은 없습니다
68 |
69 | # 기여
70 | - exe 파일을 이 명령어를 통해 생성할 수 있습니다.
71 | ```
72 | pyinstaller --noconfirm --onefile --console --add-data "\grammer.lark;." --add-data "\web;web/" "\new_compiler.py"
73 | ```
74 |
75 | # 사용된 라이브러리 목록
76 | ```python
77 | import datetime
78 | from lark import Transformer, Token, Tree, Lark
79 | import os
80 | import json
81 | import shutil
82 | import sys
83 | import time
84 | ```
85 |
86 | # 문법
87 | ## 일반
88 | ### 주석
89 | `#`을 사용해 주석을 달 수 있다
90 | ```
91 | # 이건 개쩌는 주석이다. 와!
92 | ```
93 | ### 자료형 목록
94 | - int
95 | - `1`, `-2`, `100`과 같은 정수 자료형
96 | - float, double
97 | - `1.0`, `3.14`와 같은 소수 자료형
98 | - float는 `1f`, `2.7f`처럼 뒤에 `f`를 붙여야 합니다
99 | - string
100 | - `"This is string"`과 같은 문자열 자료형
101 | - nbt
102 | - `{id:"minecraft:block_display",Tags:["temp"]}`처럼 json과 유사한 자료형
103 | ### 변수 선언
104 | `var <변수명>`의 형태로 선언한다
105 | ```
106 | var a
107 | var b = 2.0
108 | var c = "asdf"
109 | ```
110 |
111 | 배열 선언은 다른 변수와 똑같이 선언한다
112 | ```
113 | var array = [1, 2, 3]
114 | ```
115 | ### 지역변수
116 | ```
117 | var a
118 | if (조건) {
119 | var a
120 | }
121 | ```
122 | 이때, if문 안의 a와 밖의 a는 서로 다른 변수이다.
123 | 또한, if문 안에서는 a가 선언 되었으므로 밖의 a에 접근하지 못한다
124 | ### 줄바꿈
125 | 기본적으로 명령어의 끝은 `\n`이나 `;`로 표기한다
126 | - 단, `;`는 생략가능하나 필요할 경우 적어주는 것이 좋다
127 | `[ ]`, `{ }`, `( )`인 경우 괄호의 시작부터 괄호가 닫히기 전까지를 하나의 명령어로 취급한다
128 | 즉, 아래 예시에서 { test: "asdf" } 가 한 문장이다
129 | ```
130 | var a
131 | var b = {
132 | test: "asdf"
133 | }
134 | ```
135 |
136 | ```
137 | var a;
138 | var b = {
139 | test: "asdf"
140 | };
141 | ```
142 |
143 | ### 마인크래프트 명령어
144 | `/`를 맨 앞에 쓰면 그것은 마인크래프트 명령어로 인식한다
145 | ```
146 | /say a
147 | /gamemode creative @a
148 | ```
149 | 커맨드에서 `;`는 명령어의 끝으로 인식되지 않기 때문에 줄바꿈을 해주어야 한다
150 | 매크로의 경우에도 마찬가지이다
151 | ```
152 | /say a (O) /say a; /say b (X)
153 | /say b
154 | ```
155 | ### __namespace__, __main__
156 | `__namespace__`와 `__main__`는 메인 파일에서는 동일하지만 import 된 파일에서는 다르게 변환된다
157 | 아래와 같이 동일한 내용의 `test`, `test2` 파일이 있고, `test`가 `test2`를 import 한다
158 | ```
159 | def foo(){ print("foo") }
160 |
161 | /function __namespace__:foo
162 | /function __main__:foo
163 | ```
164 | 이때 `/function __namespace__:foo`와 `/functino __main__:foo`는 아래와 같이 변환된다 (네임스페이스는 pack으로 설정했다)
165 | - test
166 | ```
167 | /function pack:foo
168 | /function pack:foo
169 | ```
170 | - test2
171 | ```
172 | /function pack:test2/foo
173 | /function pack:foo
174 | ```
175 | 요컨대, `__namespace__`는 모듈까지의 경로로 변환되고 `__main__`은 오직 설정한 네임스페이스로만 변환된다
176 |
177 | ### 매크로
178 | 커맨드의 시작에 `$`를 적고, `$(변수명)`처럼 적으면 매크로처럼 사용 가능하다
179 | ```
180 | var a = 123
181 | /$say $(a)
182 | var command = "say a"
183 | /$$(command)
184 | ```
185 |
186 | ```
187 | [@] 123
188 | [@] a
189 | ```
190 | `\$`를 입력하면 컴파일 할 때 `$`로 바뀐다
191 | - 잘못된 예
192 | ```
193 | var a = 123
194 | /$say $(a) $
195 | ```
196 |
197 | ```
198 | lark.exceptions.UnexpectedToken: Unexpected token Token('__ANON_21', '$䗻\n') at line 2, column 12.
199 | Expected one of:
200 | * EOL
201 | * NO_DOLOR_WORD
202 | * ESCAPED_DOLOR
203 | * "$("
204 | * ESCAPED_MACRO
205 | Previous tokens: [Token('RPAR', ')')]
206 | ```
207 | - 옳은 예
208 | ```
209 | var a = 123
210 | /$say $(a) \$
211 | ```
212 |
213 | ```
214 | [@] 123 $
215 | ```
216 |
217 | 조금 복잡하긴 하지만 인게임 매크로도 사용 가능하다
218 | ```
219 | def foo(){
220 | /$\$say \$(text)
221 | }
222 | /function __namespace__:foo {text:"asdf"}
223 | ```
224 |
225 | ```
226 | [@] asdf
227 | ```
228 |
229 |
230 | ### 연산
231 | 괄호 > 멤버 > 산술 > 관계(부등식) > 논리(and, or) > 대입 순으로 연산이 진행된다
232 | - **!! 1.21.5 이상의 버전에서는 산술, 관계 연산이 작동하지 않습니다 !!**
233 | - 괄호
234 | - `()`
235 | - 멤버(배열의 원소에 접근하는 연산)
236 | - `[]`
237 | - 산술
238 | - `+`
239 | - `-`
240 | - `*`
241 | - `/`
242 | - `%`
243 | - `double`과 `float`의 경우, 소수점 아래 2자리까지만 값이 보존된다. 더 정확한 값을 얻고 싶다면 `divide`와 `multiply` 함수를 사용하는 것이 좋다.
244 | - 관계
245 | - `==`
246 | - `!=`
247 | - `<=`
248 | - `>=`
249 | - `<`
250 | - `>`
251 | - 논리
252 | - `and`
253 | - `or`
254 | - `!`
255 | - 대입
256 | - `=`
257 | 만약 연산의 피연산자들의 자료형이 서로 다른 경우, 에러가 발생한다
258 | 단, `double`과 `float`, `int`처럼 숫자끼리 연산하는 경우엔 에러가 나지 않는다
259 | ```
260 | 1 + "1"
261 | ```
262 |
263 | ```
264 | Runtime Error: Operand must have same type
265 | ```
266 | 연산의 결과는 연산자의 뒤쪽 피연산자를 따라갑니다
267 | ex) 0.3 * 1 = 0
268 | `!`의 경우, `!(is_module())`와 같이 뒤에 괄호를 넣어야 한다
269 | 달리 말하자면 함수처럼 써야 한다는 소리이다
270 | ### 조건문
271 | `if( <조건> ){ ~~~ }`와 같은 형식으로 작성한다
272 | 중괄호를 생략하는 경우, 조건 다음의 명령어 한 줄만 실행한다.
273 | ```
274 | var a = 0;
275 | if(a == 0){
276 | a = a + 1;
277 | }
278 | ```
279 |
280 | ```
281 | var a = 0
282 | if(a == 0)
283 | a = a + 1
284 | ```
285 | `if (...) {...} else {...}`과 같은 형태로 else를 사용할 수 있다
286 | 마찬가지로 중괄호를 생략하는 경우, 한 줄의 명령어만 실행된다
287 | ```
288 | var a = 0
289 | if(a == 1){
290 | a = a + 1
291 | } else {
292 | a = a - 1
293 | }
294 | ```
295 |
296 | ```
297 | var a = 0
298 | if(a == 1){
299 | a = a + 1
300 | } else
301 | a = a - 1
302 | ```
303 | 중괄호를 생략하면 다음 한 줄의 명령어만 실행하기 때문에 `else if` 구문도 지원한다
304 | 그러나 종종 else if를 사용하는 경우 버그가 발생할 수 있으니 되도록 중괄호를 쓰는 것을 권장한다
305 | ```
306 | var a = 0
307 | if(a == 1){
308 | a = a + 1
309 | } else if (a == 0){
310 | a = a + 2
311 | }
312 | ```
313 | 조건 안에 연산 없이 변수만 넣어도 된다
314 | ```
315 | var a = 1
316 | if(a){ # true
317 | print(a)
318 | }
319 | ```
320 | 이때, 참/거짓을 판단하는 기준은 마인크래프트의 `execute store` 구문을 따른다
321 | `store`의 결과가 0 이하라면 거짓으로 판단한다
322 | 때문에 다음과 같은 값이 들어가는 경우, 거짓이 나올 수 있다
323 | - "" (빈 문자열)
324 | - 0.4 (반올림 했을 때 0이 되는 소수)
325 | - -1 (음수)
326 | - [] (빈 배열)
327 | ### 반복문
328 | `while`의 경우, `if`와 같은 형태로 적을 수 있다
329 | ```
330 | var a = 0
331 | while(a < 10){
332 | a = a + 1
333 | }
334 | ```
335 |
336 | ```
337 | var a = 0
338 | while(a < 10)
339 | a = a + 1
340 | ```
341 | `break` 키워드를 통해 루프를 멈출 수 있다
342 | `continue`와 `for`는 지원하지 않는다
343 |
344 | ### 함수 선언
345 | `def <함수명>( [매개변수] ){...}`의 형태로 적어 함수를 선언할 수 있다
346 | `[매개변수]`는 필요에 따라 생략해도 된다
347 | ```
348 | def tick(){
349 | var a = 1
350 | }
351 | ```
352 |
353 | ```
354 | def test(var a, var b){
355 | print(a, b)
356 | }
357 | ```
358 | 함수 이름에 대문자를 사용하면 마인크래프트는 그 함수를 그냥 없는 것으로 생각한다
359 | ~~멍청이이다~~
360 | 그러니 함수명에 대문자를 쓰지 않도록 하자
361 |
362 | - `def tick`을 통해 tick이라는 이름의 함수를 선언한 경우, 이 함수는 매틱 실행된다(`#tick`에서 실행된다)
363 | - `def load`을 통해 load이라는 이름의 함수를 선언한 경우, 이 함수는 맵이 로딩될 때 1회 실행된다(`#load`에서 실행된다)
364 | - 이렇게 실행되는 `load`와 `tick`은 인자를 받을 수 없다
365 | - 아래와 같이 작성하는 경우엔 인자를 받을 수 있다
366 | ```
367 | def tick(var a){
368 | print(a)
369 | }
370 | tick("asdf")
371 | ```
372 | ### 함수 호출
373 | `함수명(인자)`와 같이 작성하여 함수를 호출 할 수 있다
374 | ```
375 | def wa(var a){
376 | return "sans"
377 | }
378 |
379 | def load(){
380 | wa(3)
381 | }
382 | ```
383 | 만약 `/function`명령어를 사용해 함수를 호출하고 싶다면 아래와 같이 쓰면 된다
384 | 이때, 인자는 가장 최근에 사용된 인자를 한번 더 사용한다 (정크 데이터를 사용한다)
385 | ```
386 | def dumb_function(var a){
387 | return a
388 | }
389 |
390 | /function __namespace__:dumb_function
391 | ```
392 | `__namespace__`는 사용자가 입력한 네임스페이스로 바뀐다
393 | 만약 모듈로서 `import` 되었다면 `__namespace__`는 `namespace:filename/`의 형식으로 바뀌므로 걱정할 필요 없다
394 |
395 |
396 | ## import
397 | `import <파일명>`의 형태로 같은 디렉토리에 있는 `파일명.planet`을 가져올 수 있다.
398 |
399 | `test.planet`
400 | ```
401 | def print_test(){
402 | print("test")
403 | }
404 | ```
405 |
406 | `main.planet`
407 | ```
408 | import test
409 | test.print_test()
410 | ```
411 |
412 | `main.planet`을 컴파일 했을 때
413 | ```
414 | test
415 | ```
416 |
417 | ## execute
418 | 1. `if function`을 제외하고는 거의 대부분 마크 문법 그대로 사용해도 된다.
419 | ### if function
420 | - 함수를 정의했다면 `execute(if function __namespace__:test)`의 형태로 사용 가능하다
421 | - 함수를 정의하지 않고 아래와 같은 형태로도 사용 가능하다
422 | ```
423 | execute(if function {
424 | return 1
425 | } positioned 0 0 0){
426 | print("성공!")
427 | }
428 | ```
429 |
430 |
431 | ## 내장 함수
432 | ### 함수명(자료형 인자, ...)
433 | `함수명`에 관한 설명
434 | `자료형`이 `any`로 적혀있는 경우, 어떤 자료형이든 상관 없다는 얘기이다.
435 | `...`이 있는 경우엔 인자가 몇개든 들어갈 수 있다는 것이다
436 | ### print(any a1, any a2, ...)
437 | `a1 a2 ...`의 형태로 채팅창에 출력된다
438 | ```
439 | var a = 123
440 | print(a)
441 | ```
442 |
443 | ```
444 | 123
445 | ```
446 | ### random()
447 | 0~1 사이의 랜덤한 실수를 반환한다
448 | ```
449 | random()
450 | ```
451 | ### type(any a)
452 | `a`의 자료형을 문자열로 반환한다
453 | ```
454 | var test = 1.0
455 | print(type(test))
456 | ```
457 |
458 | ```
459 | float
460 | ```
461 | ### round(float|double a)
462 | `float` 또는 `double` 자료형을 반올림하여 `int`로 반환한다
463 | ```
464 | print(round(1.2))
465 | ```
466 |
467 | ```
468 | 1
469 | ```
470 | ### get_score(string player, string objective)
471 | `player`의 `objective` 점수를 가져온다
472 | `/scoreboard players get {player} {objective}`와 같은 역할이다
473 | ```
474 | /scoreboard objectives add test dummy
475 | /scoreboard players set asdf test 100
476 | print(get_score("asdf", "test"))
477 | ```
478 |
479 | ```
480 | 100
481 | ```
482 | ### set_score(string player, string objective, any var)
483 | `player`의 `objective`에 `var`의 값을 스코어로 넣는다
484 | `/scoreboard players set {player} {objective} {var}`와 같은 역할이다
485 | `var`를 반환한다
486 | ```
487 | var a = 10
488 | print(set_score("test", "num", a))
489 | /tellraw @a {"score":{"name":"test","objective":"num"}}
490 | ```
491 |
492 | ```
493 | 10
494 | 10
495 | ```
496 | ### get_data(string from, string|entity name, string dir)
497 | - `from`은 `entity`, `block`, `storage` 중 한가지여야 한다.
498 | - `name`은 블록의 좌표, 저장소의 이름, 엔티티 중 한가지여야 한다
499 | - `dir`은 가져오고자 하는 nbt의 경로를 뜻한다
500 | `/data get {from} {name} {dir}`와 같은 역할이다
501 | ```
502 | /data modify storage minecraft:test test_dir set value "it's test string!"
503 | print(get_data("storage", "minecraft:test", "test_dir"))
504 | ```
505 |
506 | ```
507 | it's test string!
508 | ```
509 | ### set_data(string from, string|entity name, string dir, any var)
510 | - `from`은 `entity`, `block`, `storage` 중 한가지여야 한다.
511 | - `name`은 블록의 좌표, 저장소의 이름, 엔티티 중 한가지여야 한다
512 | - `dir`은 설정하고자 하는 nbt의 경로를 뜻한다
513 | `/data modify {from} {name} {dir} set value {var}`와 같은 역할이다
514 | ```
515 | set_data("storage", "minecraft:test", "test_dir", "it's test string!")
516 | print(get_data("storage", "minecraft:test", "test_dir"))
517 | ```
518 | ### append(any[] arr, any element)
519 | - `arr`은 원소를 추가할 배열이다.
520 | - `element`는 추가할 원소이다
521 | ` `/data modify storage 40planet:values {arr} append value {element}`와 같은 역할이다
522 | ```
523 | var arr = []
524 | append(arr, 1)
525 | var test = 2
526 | append(arr, test)
527 | print(arr)
528 | ```
529 | ### del(any var)
530 | - 저장소에서 `var`을 지웁니다
531 | - 예) `del(arr[1])`
532 | - `/data remove storage 40planet:values {var}`와 같은 역할이다
533 | ### len(any var)
534 | - 배열 또는 string 타입만 받습니다
535 | - `var`의 길이를 반환합니다
536 | ### is_module()
537 | - 해당 파일이 모듈로써 불러와진 것인지 판단해준다
538 | - 파이썬의 `__name__ == "__main__"` 조건문 역할을 해준다.
539 | ```
540 | if(is_module()){
541 | print("this is not main")
542 | }
543 | ```
544 | ### divide(int|float|double var, int|float|double var2)
545 | - `var / var2`를 소수점 아래 5자리까지 계산해준다
546 | - 반환값의 타입은 `float`이다
547 | ```
548 | print(divide(1, 2))
549 | ```
550 | ### multiply(int|float|double var, int|float|double var2)
551 | - `var * var2`를 소수점 아래 5자리까지 계산해준다
552 | - 반환값의 타입은 `float`이다
553 | ```
554 | print(multiply(2, 3))
555 | ```
556 | ### int(any a)
557 | `a`를 `int` 자료형으로 변환해준다
558 | `float` 또는 `double`의 경우엔 `round(a)`와 같다
559 | ```
560 | print(int(1.2))
561 | print(int("3"))
562 | ```
563 |
564 | ```
565 | 1
566 | 3
567 | ```
568 | ### float(any a)
569 | `a`를 `float`로 변환해준다
570 | ```
571 | print(float(1))
572 | ```
573 |
574 | ```
575 | 1.0f
576 | ```
577 | ### double(any a)
578 | `a`를 `double`로 변환해준다
579 | ```
580 | print(double(1))
581 | ```
582 |
583 | ```
584 | 1.0d
585 | ```
586 | ### bool(any a)
587 | `a`를 `bool`로 변환해준다
588 | ```
589 | print(bool(100))
590 | ```
591 |
592 | ```
593 | 1
594 | ```
595 | ### string(any a)
596 | `a`를 `string`으로 변환해준다
597 | ```
598 | print(string(1 + 1))
599 | ```
600 |
601 | ```
602 | 2
603 | ```
604 |
--------------------------------------------------------------------------------
/rpg_planet/main_display.planet:
--------------------------------------------------------------------------------
1 | import id
2 | import skill
3 | import stat
4 | # import blocks
5 |
6 |
7 | /scoreboard objectives add 40planet_inv_idx dummy
8 | /scoreboard objectives add 40planet_rpg_first dummy
9 | /scoreboard objectives add 40planet_rpg_equipment_health dummy
10 | /scoreboard objectives add 40planet_rpg_equipment_strength dummy
11 | /scoreboard objectives add 40planet_rpg_equipment_speed dummy
12 | /scoreboard objectives add 40planet_rpg_equipment_mana dummy
13 | /scoreboard objectives add 40planet_rpg_leave minecraft.custom:minecraft.leave_game
14 |
15 | var inv_ui;
16 | var player_id;
17 | var inv_ui_len;
18 |
19 |
20 | def first_load_player(){
21 | /scoreboard players set @s 40planet_inv_idx 0
22 | /scoreboard players set @s 40planet_rpg_first 0
23 | player_id = id.set_id()
24 | /data modify storage 40planet:rpg players.^player_id&.armor set value [{}, {}, {}, {}, {}, {}, {}]
25 | /item replace entity @s container.17 with command_block[minecraft:custom_data={40planet_inv_btn:1b,40planet_ui:1b},minecraft:custom_name='{"text":"메뉴","italic":false}']
26 | }
27 |
28 | # slot번째 슬롯의 아이템 돌려주고 지우기
29 | def return_item(var slot){
30 | /execute in minecraft:overworld run item replace block 15 -60 15 container.1 from entity @s container.^slot&
31 | /execute in minecraft:overworld unless items block 15 -60 15 container.1 * run return 0
32 | /item replace entity @s container.^slot& with air
33 | /execute at @s anchored eyes positioned ^ ^ ^ run summon item ~ ~ ~ {PickupDelay:0s,Item:{id:"stone",count:1b},Tags:["40planet_rpg_item"]}
34 | execute(as @e[tag=40planet_rpg_item,limit=1]){
35 | /execute in minecraft:overworld run item replace entity @s container.0 from block 15 -60 15 container.1
36 | /tag @s remove 40planet_rpg_item
37 | }
38 | }
39 |
40 | def update_stat(){ # 장비 스텟 + 기본 스텟 적용하기
41 | /scoreboard players set @s 40planet_rpg_leave 0
42 |
43 | /scoreboard players operation @s 40planet_rpg_health += @s 40planet_rpg_equipment_health
44 | /scoreboard players operation @s 40planet_rpg_strength += @s 40planet_rpg_equipment_strength
45 | /scoreboard players operation @s 40planet_rpg_speed += @s 40planet_rpg_equipment_speed
46 | /scoreboard players operation @s 40planet_rpg_mana += @s 40planet_rpg_equipment_mana
47 | stat.update_attribute()
48 | /scoreboard players operation @s 40planet_rpg_health -= @s 40planet_rpg_equipment_health
49 | /scoreboard players operation @s 40planet_rpg_strength -= @s 40planet_rpg_equipment_strength
50 | /scoreboard players operation @s 40planet_rpg_speed -= @s 40planet_rpg_equipment_speed
51 | /scoreboard players operation @s 40planet_rpg_mana -= @s 40planet_rpg_equipment_mana
52 | }
53 |
54 |
55 | def add_stat(var type, var value){ # 스텟 + value, 스텟포인트 - 1
56 | execute (if score "@s" "40planet_stat_point" matches ..0){
57 | /tellraw @s {"text":"스텟포인트가 부족합니다","color":"red"}
58 | /execute at @s run playsound minecraft:block.note_block.bass weather @s ~ ~ ~ 1 1
59 | return 1
60 | }
61 | /scoreboard players add @s 40planet_rpg_^type& ^value&
62 | /scoreboard players remove @s 40planet_stat_point 1
63 | update_stat()
64 | }
65 |
66 | def click_2_19(){ # 체력
67 | execute(if items entity @s container.19 *){
68 | return_item(19)
69 | }
70 | add_stat("health", 1)
71 | /return 1
72 | }
73 | def click_2_21(){ # 근력
74 | execute(if items entity @s container.21 *){
75 | return_item(21)
76 | }
77 | add_stat("strength", 1)
78 | /return 1
79 | }
80 | def click_2_23(){ # 민첩
81 | execute(if items entity @s container.23 *){
82 | return_item(23)
83 | }
84 | add_stat("speed", 1)
85 | /return 1
86 | }
87 | def click_2_25(){ # 마나
88 | execute(if items entity @s container.21 *){
89 | return_item(25)
90 | }
91 | add_stat("mana", 1)
92 | /return 1
93 | }
94 |
95 | # 장비의 업그레이드 스텟 추가해주는 함수
96 | def update_equipment_stat(){
97 | /scoreboard players set @s 40planet_rpg_equipment_health 0
98 | /scoreboard players set @s 40planet_rpg_equipment_strength 0
99 | /scoreboard players set @s 40planet_rpg_equipment_speed 0
100 | /scoreboard players set @s 40planet_rpg_equipment_mana 0
101 |
102 | /execute unless data storage 40planet:rpg players.^player_id&.armor run data modify storage 40planet:rpg players.^player_id&.armor set value [{}, {}, {}, {}, {}, {}, {}]
103 | /data modify storage 40planet:rpg players.armor set from storage 40planet:rpg players.^player_id&.armor
104 | var armor_data = get_data("storage", "40planet:rpg", "players.armor")
105 | var j = 0;
106 | while(j < 7){
107 | /execute in minecraft:overworld run item replace block 15 -60 15 container.0 with air
108 | /execute in minecraft:overworld run item replace block 15 -60 15 container.1 with stone
109 | armor_data[j].Slot = 1b
110 | execute(in minecraft:overworld){set_data("block", "15 -60 15", "Items[0]", armor_data[j])}
111 | execute(in minecraft:overworld if data block "15 -60 15" "Items[0].components.'minecraft:custom_data'.upgrade"){
112 | var upgrade = get_data("block", "15 -60 15", "Items[0].components.'minecraft:custom_data'.upgrade")
113 | var i = 0;
114 | var len = len(upgrade)
115 | while(i < len){
116 | var type = upgrade[0].type
117 | var value = upgrade[0].value
118 | set_score("value", "40planet_num", value)
119 | /execute if score value 40planet_num matches 1.. run scoreboard players add @s 40planet_rpg_equipment_^type& ^value&
120 | /execute if score value 40planet_num matches ..0 run scoreboard players remove @s 40planet_rpg_equipment_^type& ^value&
121 | del(upgrade[0])
122 | i = i + 1;
123 | }
124 | }
125 | j = j + 1;
126 | }
127 | update_stat()
128 | }
129 |
130 | # 갑옷 장착, 해제 함수
131 | def armor_slot(var slot, var idx){
132 | /execute in minecraft:overworld run item replace block 15 -60 15 container.0 from entity @s container.^slot&
133 | execute(if score "is_correct_slot" "40planet_num" matches 0){
134 | /execute at @s run playsound minecraft:item.armor.equip_iron weather @s ~ ~ ~
135 | /data modify storage 40planet:rpg players.^player_id&.armor[^idx&] set value {}
136 | update_equipment_stat()
137 | return_item(slot)
138 | return 1
139 | }
140 | /execute store success score temp 40planet_num in minecraft:overworld run data modify storage 40planet:rpg players.^player_id&.armor[^idx&] set from block 15 -60 15 Items[0]
141 | /execute if score temp 40planet_num matches 1 at @s run playsound minecraft:item.armor.equip_iron weather @s ~ ~ ~
142 | # update_armor_slot(slot, idx, true)
143 | update_equipment_stat()
144 | /scoreboard players set not_change_inv 40planet_num 1
145 | /clear @s *[minecraft:custom_data~{40planet_ui_^slot&:1b}]
146 | return 1
147 | }
148 | def click_3_11(){ # 투구
149 | # print("투구")
150 | /execute store result score is_correct_slot 40planet_num if items entity @s container.11 *[minecraft:custom_data~{40planet_helmet:1b}]
151 | return armor_slot(11, 0)
152 | }
153 |
154 | def click_4_13(){ # 무기 슬롯
155 | execute(unless items entity @s container.13 *[minecraft:custom_data~{40planet_equipment:1b}]){
156 | return_item(13)
157 | return 1
158 | }
159 |
160 | /kill "98a261f6-84b5-4c36-ad3f-818aec8c7404"
161 | /summon armor_stand ~ ~ ~ {UUID:[I;-1734188554,-2068493258,-1388346998,-326339580]}
162 |
163 | /item replace block 15 -60 15 container.0 from entity @s container.13
164 | /execute store success score temp 40planet_num run data modify storage 40planet:rpg players.^player_id&.skill_item set from block 15 -60 15 Items[0]
165 |
166 | # 장비가 아닌 다른 것을 옮김
167 | execute(if score "temp" "40planet_num" matches 0 in minecraft:overworld){ # 인벤토리 -> 컴포넌트
168 | /item replace block 15 -60 15 container.1 from entity @s container.29
169 | /data modify block 15 -60 15 Items[0].components."minecraft:custom_data".skill.f set from block 15 -60 15 Items[1]
170 | /execute unless data block 15 -60 15 Items[1] run data modify block 15 -60 15 Items[0].components."minecraft:custom_data".skill.f set value {}
171 | /item replace block 15 -60 15 container.1 from entity @s container.31
172 | /data modify block 15 -60 15 Items[0].components."minecraft:custom_data".skill.click set from block 15 -60 15 Items[1]
173 | /execute unless data block 15 -60 15 Items[1] run data modify block 15 -60 15 Items[0].components."minecraft:custom_data".skill.click set value {}
174 | /item replace block 15 -60 15 container.1 from entity @s container.33
175 | /data modify block 15 -60 15 Items[0].components."minecraft:custom_data".skill.sneak_click set from block 15 -60 15 Items[1]
176 | /execute unless data block 15 -60 15 Items[1] run data modify block 15 -60 15 Items[0].components."minecraft:custom_data".skill.sneak_click set value {}
177 | /item replace entity @s container.13 from block 15 -60 15 container.0
178 | /execute store success score temp 40planet_num run data modify storage 40planet:rpg players.^player_id&.skill_item set from block 15 -60 15 Items[0]
179 | }
180 | # 장비를 옮김
181 | execute(if score "temp" "40planet_num" matches 1 in minecraft:overworld){ # 컴포넌트 -> 인벤토리
182 | /execute at @s run playsound minecraft:item.armor.equip_iron weather @s ~ ~ ~
183 | /data modify entity "98a261f6-84b5-4c36-ad3f-818aec8c7404" HandItems[0] set from block 15 -60 15 Items[0].components."minecraft:custom_data".skill.f
184 | /execute if data block 15 -60 15 Items[0].components."minecraft:custom_data".skill.f run item replace entity @s container.29 from entity "98a261f6-84b5-4c36-ad3f-818aec8c7404" weapon
185 | /data modify entity "98a261f6-84b5-4c36-ad3f-818aec8c7404" HandItems[0] set from block 15 -60 15 Items[0].components."minecraft:custom_data".skill.click
186 | /execute if data block 15 -60 15 Items[0].components."minecraft:custom_data".skill.click run item replace entity @s container.31 from entity "98a261f6-84b5-4c36-ad3f-818aec8c7404" weapon
187 | /data modify entity "98a261f6-84b5-4c36-ad3f-818aec8c7404" HandItems[0] set from block 15 -60 15 Items[0].components."minecraft:custom_data".skill.sneak_click
188 | /execute if data block 15 -60 15 Items[0].components."minecraft:custom_data".skill.sneak_click run item replace entity @s container.33 from entity "98a261f6-84b5-4c36-ad3f-818aec8c7404" weapon
189 | }
190 |
191 | /scoreboard players set not_change_inv 40planet_num 1
192 | # print("스킬 장비칸")
193 | /clear @s *[custom_data~{40planet_ui_skill:1b}]
194 | /kill "98a261f6-84b5-4c36-ad3f-818aec8c7404"
195 | /execute in minecraft:overworld run item replace block 15 -60 15 container.0 with air
196 | /return 1
197 | }
198 | def click_4_29(){ # F
199 | /scoreboard players set not_change_inv 40planet_num 1
200 | /scoreboard players set temp 40planet_num 0
201 | /execute unless items entity @s container.29 *[minecraft:custom_data~{40planet_skill:1b}] run scoreboard players set temp 40planet_num 1
202 | /execute unless items entity @s container.13 *[minecraft:custom_data~{40planet_equipment:1b}] run scoreboard players set temp 40planet_num 1
203 | execute(if score "temp" "40planet_num" matches 1){
204 | return_item(29)
205 | }
206 | /return 1
207 | }
208 | def click_4_31(){ # 우클릭
209 | /scoreboard players set not_change_inv 40planet_num 1
210 | /scoreboard players set temp 40planet_num 0
211 | /execute unless items entity @s container.31 *[minecraft:custom_data~{40planet_skill:1b}] run scoreboard players set temp 40planet_num 1
212 | /execute unless items entity @s container.13 *[minecraft:custom_data~{40planet_equipment:1b}] run scoreboard players set temp 40planet_num 1
213 | execute(if score "temp" "40planet_num" matches 1){
214 | return_item(31)
215 | }
216 | /return 1
217 | }
218 | def click_4_33(){ # Shift + 우클릭
219 | /scoreboard players set not_change_inv 40planet_num 1
220 | /scoreboard players set temp 40planet_num 0
221 | /execute unless items entity @s container.33 *[minecraft:custom_data~{40planet_skill:1b}] run scoreboard players set temp 40planet_num 1
222 | /execute unless items entity @s container.13 *[minecraft:custom_data~{40planet_equipment:1b}] run scoreboard players set temp 40planet_num 1
223 | execute(if score "temp" "40planet_num" matches 1){
224 | return_item(33)
225 | }
226 | /return 1
227 | }
228 |
229 |
230 | def summon_window(){
231 | execute(summon minecraft:block_display){
232 | /data merge entity @s {Tags:["rpg_window_marker","unset","40planet_gui_entity"]}
233 | /tp @s ~ ~ ~ ~180 0
234 | }
235 | execute(summon minecraft:text_display){
236 | /data merge entity @s {Tags:["unset","40planet_gui_entity"],transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[7f,10f,1f],translation:[-.085f,1.5f,-.15f]}}
237 | /tp @s ~ ~ ~ ~180 0
238 | }
239 | execute(summon minecraft:text_display){
240 | /data merge entity @s {Tags:["unset","40planet_gui_entity"],transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[.1f,.1f,1f],translation:[0f,1.7f,-.15f]},text:'{"text":"[ 스텟 ]","bold":true}',background:0}
241 | /tp @s ~ ~ ~ ~180 0
242 | }
243 | execute(summon minecraft:text_display){
244 | /data merge entity @s {Tags:["unset","40planet_gui_entity"],transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[.1f,.1f,1f],translation:[0f,1.61f,-.15f]},text:'{"text":"[ 장비 ]","bold":true}',background:0}
245 | /tp @s ~ ~ ~ ~180 0
246 | }
247 | execute(summon minecraft:text_display){
248 | /data merge entity @s {Tags:["unset","40planet_gui_entity"],transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[.1f,.1f,1f],translation:[0f,1.52f,-.15f]},text:'{"text":"[ 스킬 ]","bold":true}',background:0}
249 | /tp @s ~ ~ ~ ~180 0
250 | /data modify storage 40planet:rpg window.rotation set from entity @s Rotation
251 | }
252 | /execute rotated ~180 0 run summon minecraft:interaction ^ ^1.70 ^-.15 {Tags:["unset","40planet_gui_entity","stat"],height:.03f,width:.1f,response:1b}
253 | /execute rotated ~180 0 run summon minecraft:interaction ^ ^1.61 ^-.15 {Tags:["unset","40planet_gui_entity","equip"],height:.03f,width:.1f,response:1b}
254 | /execute rotated ~180 0 run summon minecraft:interaction ^ ^1.52 ^-.15 {Tags:["unset","40planet_gui_entity","skill"],height:.03f,width:.1f,response:1b}
255 |
256 | /scoreboard players operation #temp 40planet_num = @s 40planet_id
257 | execute(as @e[distance=..2,tag=unset]){
258 | /scoreboard players operation @s 40planet_id = #temp 40planet_num
259 | /tag @s remove unset
260 | /data modify entity @s Rotation set from storage 40planet:rpg window.rotation
261 | }
262 | }
263 |
264 | def summon_stat_window(){
265 | /scoreboard players operation #temp 40planet_num = @s 40planet_id
266 | execute(summon minecraft:text_display){
267 | /data merge entity @s {Tags:["40planet_gui_entity","stat_window"],transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[7f,10f,1f],translation:[-.085f,1.5f,-.15f]}}
268 | /tp @s ~ ~ ~ ~ 0
269 | /scoreboard players operation @s 40planet_id = #temp 40planet_num
270 | }
271 | }
272 |
273 | def tick(){
274 | /execute unless entity a3924728-f122-470f-977a-79ec38d81808 run summon item_display 0 -60 0 {UUID:[I;-1550694616,-249411825,-1753581076,953686024]}
275 |
276 | execute(as @a unless items entity @s container.17 *[minecraft:custom_data~{40planet_inv_btn:1b}] at @s){
277 | summon_window()
278 |
279 | /clear @s command_block[minecraft:custom_data~{40planet_inv_btn:1b}]
280 | /execute in minecraft:overworld run item replace entity a3924728-f122-470f-977a-79ec38d81808 container.0 from entity @s container.17
281 | /item replace entity @s container.17 with command_block[minecraft:custom_data={40planet_inv_btn:1b}]
282 | /execute in minecraft:overworld unless items entity a3924728-f122-470f-977a-79ec38d81808 container.0 * run return 0
283 | /execute at @s anchored eyes positioned ^ ^ ^ run summon item ~ ~ ~ {PickupDelay:0s,Item:{id:"stone",count:1b},Tags:["40planet_rpg_item"]}
284 | execute(as @e[tag=40planet_rpg_item,limit=1]){
285 | /execute in minecraft:overworld run item replace entity @s container.0 from entity a3924728-f122-470f-977a-79ec38d81808 container.0
286 | /tag @s remove 40planet_rpg_item
287 | }
288 |
289 | }
290 |
291 | execute(as @e[tag=40planet_gui_entity]){
292 | execute(if entity @s[tag=rpg_window_marker] at @s unless entity @a[distance=..0.0001]){
293 | /scoreboard players operation #temp 40planet_num = @s 40planet_id
294 | /execute as @e[tag=40planet_gui_entity,distance=..2] if score @s 40planet_id = #temp 40planet_num run kill @s
295 | /kill @s
296 | }
297 |
298 | execute(if entity @s[type=interaction] if data entity "@s" "interaction" at @s){
299 | /scoreboard players operation #temp 40planet_num = @s 40planet_id
300 | /execute as @a if score @s 40planet_id = #temp 40planet_num run tag @s add 40planet_rpg_window_owner
301 | /execute if entity @s[tag=stat] rotated ~75 ~ positioned as @p[tag=40planet_rpg_window_owner] run function __namespace__:summon_stat_window
302 | /tag @a remove 40planet_rpg_window_owner
303 | /data remove entity @s interaction
304 | }
305 | }
306 |
307 |
308 | }
--------------------------------------------------------------------------------
/rpg_planet/blocks.planet:
--------------------------------------------------------------------------------
1 | /scoreboard objectives add 40planet_rpg_success_per dummy
2 | /scoreboard objectives add 40planet_rpg_fail_per dummy
3 | /scoreboard objectives add 40planet_rpg_destroy_per dummy
4 | /scoreboard players set 10 40planet_num 10
5 |
6 | var reinforce_cnt;
7 | var success_per = [
8 | [100.0, 0.0, 0.0], # 0
9 | [90.0, 10.0, 0.0], # 1
10 | [85.0, 15.0, 0.0], # 2
11 | [85.0, 15.0, 0.0], # 3
12 | [80.0, 20.0, 0.0], # 4
13 | [75.0, 25.0, 0.0], # 5
14 | [70.0, 30.0, 0.0], # 6
15 | [65.0, 35.0, 0.0], # 7
16 | [60.0, 40.0, 0.0], # 8
17 | [55.0, 45.0, 0.0], # 9
18 | [50.0, 50.0, 0.0], # 10
19 | [45.0, 55.0, 0.0], # 11
20 | [40.0, 60.0, 0.0], # 12
21 | [35.0, 65.0, 0.0], # 13
22 | [30.0, 70.0, 0.0], # 14
23 | [30.0, 67.9, 2.1], # 15
24 | [30.0, 67.9, 2.1], # 16
25 | [30.0, 67.9, 2.1], # 17
26 | [30.0, 67.2, 2.8], # 18
27 | [30.0, 67.2, 2.8], # 19
28 | [30.0, 63.0, 7.0], # 20
29 | [30.0, 63.0, 7.0], # 21
30 | [3.0, 77.6, 19.4], # 22
31 | [2.0, 68.6, 29.4], # 23
32 | [1.0, 59.6, 39.4], # 24
33 | [-1.0, -1.0, -1.0], # 25
34 | ]
35 |
36 | def tick(){
37 | /execute unless entity @e[tag=reinforce_table] run scoreboard players set $reinforce_table_id 40planet_id 0
38 | execute(as @e[tag=40planet_rpg_entity]){
39 | execute (if entity @s[tag=summon_reinforce_table] at @s align xyz positioned "~.5 ~1 ~.5"){
40 | /kill @s
41 | /setblock ~ ~-.1 ~ minecraft:blackstone
42 | /scoreboard players add $reinforce_table_id 40planet_id 1
43 | /summon item_display ~ ~ ~ {Passengers:[{alignment:"left",background:0,id:"minecraft:text_display",shadow:1b,text:'""',transformation:{left_rotation:[0f,1f,0f,0f],right_rotation:[0f,0f,0f,1f],scale:[1f,1f,1f],translation:[0f,0.1775f,0.375f]}},{alignment:"left",background:0,id:"minecraft:text_display",shadow:1b,text:'""',transformation:{left_rotation:[0f,1f,0f,0f],right_rotation:[0f,0f,0f,1f],scale:[1f,1f,1f],translation:[0f,0.1775f,0.375f]},Rotation:[180f,0f]}],Tags:["reinforce_table","40planet_rpg_entity","unset"],item:{components:{"minecraft:enchantments":{levels:{"minecraft:sharpness":1}}},count:1,id:"minecraft:smithing_table"},transformation:{left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[1.01f,1.01f,1.01f],translation:[0f,-0.5f,0f]}}
44 | /summon item_display ~ ~.01 ~-.1875 {Tags:["unset","40planet_rpg_entity","reinforce_table_slot","reinforce_table_weapon"],Passengers:[{id:"interaction",response:1b,height:.1,width:.3}],item:{count:1,id:"minecraft:structure_void",components:{"minecraft:custom_data":{40planet_ui:1b}}},transformation:{left_rotation:[0.7071068f,0f,0f,0.7071068f],right_rotation:[0f,0f,0f,1f],scale:[0.31250003f,0.3125001f,0.43750042f],translation:[0f,0f,0f]}}
45 | /summon item_display ~-.25 ~.01 ~.1875 {Tags:["unset","40planet_rpg_entity","reinforce_table_slot"],Passengers:[{id:"interaction",response:1b,height:.1,width:.3}],item:{count:1,id:"minecraft:structure_void",components:{"minecraft:custom_data":{40planet_ui:1b}}},transformation:{left_rotation:[0.7071068f,0f,0f,0.7071068f],right_rotation:[0f,0f,0f,1f],scale:[0.31250003f,0.3125001f,0.43750042f],translation:[0f,0f,0f]}}
46 | /summon item_display ~.25 ~.01 ~.1875 {Tags:["unset","40planet_rpg_entity","reinforce_table_slot"],Passengers:[{id:"interaction",response:1b,height:.1,width:.3}],item:{count:1,id:"minecraft:structure_void",components:{"minecraft:custom_data":{40planet_ui:1b}}},transformation:{left_rotation:[0.7071068f,0f,0f,0.7071068f],right_rotation:[0f,0f,0f,1f],scale:[0.31250003f,0.3125001f,0.43750042f],translation:[0f,0f,0f]}}
47 | execute(as @e[distance=..0.5,tag=unset]){
48 | /scoreboard players operation @s 40planet_id = $reinforce_table_id 40planet_id
49 | /tag @s remove unset
50 | }
51 | /playsound minecraft:block.stone.place block @a ~ ~ ~
52 | }
53 | /execute if entity @s[tag=reinforce_table] at @s run function __namespace__:reinforce_table
54 | execute(if entity @s[tag=reinforce_text] at @s){
55 | /tp @s ~ ~.05 ~
56 | /scoreboard players add @s 40planet_num 1
57 | /execute if score @s 40planet_num matches 10 run kill @s
58 | }
59 | }
60 | execute(as @e[tag=,type=item]){
61 | /tag @s add at_e
62 | /data modify entity @s CustomName set from entity @s Item.components."minecraft:custom_name"
63 | /data modify entity @s CustomNameVisible set value 1b
64 | }
65 | }
66 |
67 | var target_attack
68 | def return_item(){
69 | /execute in minecraft:overworld run item replace block 15 -60 15 container.1 from entity @s container.0
70 | /execute on passengers on ^target_attack& at @s run summon item ~ ~1.5 ~ {PickupDelay:0s,Item:{id:"stone",count:1b},Tags:["40planet_rpg_item"]}
71 | /execute unless items entity @s container.0 *[minecraft:custom_data~{40planet_ui:1b}] on passengers unless data entity @s attack unless data entity @s interaction at @s run summon item ~ ~ ~ {PickupDelay:0s,Item:{id:"stone",count:1b},Tags:["40planet_rpg_item"]}
72 | /item replace entity @s container.0 with minecraft:structure_void[minecraft:custom_data={40planet_ui:1b}]
73 | execute(as @n[tag=40planet_rpg_item]){
74 | /execute in minecraft:overworld run item replace entity @s container.0 from block 15 -60 15 container.1
75 | /tag @s remove 40planet_rpg_item
76 | }
77 | }
78 |
79 | def update_text(){
80 |
81 |
82 | /scoreboard players operation temp 40planet_num = @s 40planet_id
83 | execute(as @e[distance=..0.5,tag=reinforce_table_slot] if score "@s" "40planet_id" = "temp" "40planet_num"){
84 | /execute if items entity @s container.0 *[custom_data~{40planet_ui:1b}] run return 0
85 | execute(if entity @s[tag=reinforce_table_weapon]){
86 | execute(if data entity "@s" 'item.components."minecraft:custom_data".percent'){
87 | /execute store result score success 40planet_num run data get entity @s item.components."minecraft:custom_data".percent[0] 10
88 | /execute store result score fail 40planet_num run data get entity @s item.components."minecraft:custom_data".percent[1] 10
89 | /execute store result score destroy 40planet_num run data get entity @s item.components."minecraft:custom_data".percent[2] 10
90 | }
91 | execute(unless data entity "@s" 'item.components."minecraft:custom_data".percent'){
92 | /data modify entity @s item.components."minecraft:custom_data".percent set value [100.0, .0, .0]
93 | /scoreboard players set success 40planet_num 1000
94 | /scoreboard players set fail 40planet_num 0
95 | /scoreboard players set destroy 40planet_num 0
96 | }
97 | }
98 | execute(unless entity @s[tag=reinforce_table_weapon] if items entity @s container.0 *[custom_data~{40planet_rpg_stone:1b}]){
99 | /execute store result score temp 40planet_num run data get entity @s item.components."minecraft:custom_data".percent 10
100 | /scoreboard players operation success 40planet_num += temp 40planet_num
101 | /scoreboard players operation fail 40planet_num -= temp 40planet_num
102 | execute(if score "fail" "40planet_num" matches ..-1){
103 | /scoreboard players operation destroy 40planet_num += fail 40planet_num
104 | /scoreboard players set fail 40planet_num 0
105 | /execute if score destroy 40planet_num matches ..-1 run scoreboard players set destroy 40planet_num 0
106 | }
107 | }
108 | }
109 |
110 | execute (if score "success" "40planet_num" matches 0 if score "fail" "40planet_num" matches 0 if score "destroy" "40planet_num" matches 0){
111 | /execute on passengers run data modify entity @s text set value '""'
112 | return 0
113 | }
114 |
115 | /scoreboard players operation @s 40planet_rpg_success_per = success 40planet_num
116 | /scoreboard players operation @s 40planet_rpg_fail_per = fail 40planet_num
117 | /scoreboard players operation @s 40planet_rpg_destroy_per = destroy 40planet_num
118 |
119 | /scoreboard players operation success_ 40planet_num = success 40planet_num
120 | /scoreboard players operation fail_ 40planet_num = fail 40planet_num
121 | /scoreboard players operation destroy_ 40planet_num = destroy 40planet_num
122 |
123 | /scoreboard players operation success 40planet_num /= 10 40planet_num
124 | /scoreboard players operation fail 40planet_num /= 10 40planet_num
125 | /scoreboard players operation destroy 40planet_num /= 10 40planet_num
126 | /scoreboard players operation success_ 40planet_num %= 10 40planet_num
127 | /scoreboard players operation fail_ 40planet_num %= 10 40planet_num
128 | /scoreboard players operation destroy_ 40planet_num %= 10 40planet_num
129 |
130 |
131 | /execute on passengers run data modify entity @s text set value '["",{"text":"성공: ","color":"green"},{"score":{"name":"success","objective":"40planet_num"}},".",{"score":{"name":"success_","objective":"40planet_num"}},{"text":"\\n실패: ","color":"red"},{"score":{"name":"fail","objective":"40planet_num"}},".",{"score":{"name":"fail_","objective":"40planet_num"}},{"text":"\\n파괴: ","color":"dark_red"},{"score":{"name":"destroy","objective":"40planet_num"}},".",{"score":{"name":"destroy_","objective":"40planet_num"}}]'
132 | }
133 |
134 | # 강화석, 스크롤 지우기
135 | def remove_items(){
136 | /data modify storage 40planet:rpg scrolls set value []
137 | execute(as @e[distance=..0.5,tag=reinforce_table_slot,tag=!reinforce_table_weapon] if score "@s" "40planet_id" = "temp" "40planet_num"){
138 | # 스크롤 정보 저장
139 | execute(if items entity @s container.0 *[custom_data~{40planet_rpg_scroll:1b}]){
140 | /data modify storage 40planet:rpg scrolls append from entity @s item.components."minecraft:custom_data"
141 | }
142 | /item replace entity @s container.0 with minecraft:structure_void[minecraft:custom_data={40planet_ui:1b}]
143 | }
144 | }
145 |
146 |
147 | def upgrade(var type, var value){
148 | /execute unless data entity @s item.components."minecraft:custom_data".upgrade run data modify entity @s item.components."minecraft:custom_data".upgrade set value [{type:"health",value:0},{type:"strength",value:0},{type:"speed",value:0},{type:"mana",value:0}]
149 | /execute store result score value 40planet_num run data get entity @s item.components."minecraft:custom_data".upgrade[{type:"^type&"}].value
150 | /execute store result entity @s item.components."minecraft:custom_data".upgrade[{type:"^type&"}].value int 1 run scoreboard players add value 40planet_num ^value&
151 |
152 | while(true){
153 | /data remove storage 40planet:rpg temp
154 | /data modify storage 40planet:rpg temp.lore set string entity @s item.components."minecraft:lore"[-1] 1 32
155 | /execute unless data storage 40planet:rpg temp{lore:"\"color\":\"yellow\",\"italic\":false"} run return 0
156 | /data remove entity @s item.components."minecraft:lore"[-1]
157 | }
158 | var health = get_data("entity", "@s", "item.components.'minecraft:custom_data'.upgrade[0].value")
159 | var strength = get_data("entity", "@s", "item.components.'minecraft:custom_data'.upgrade[1].value")
160 | var speed = get_data("entity", "@s", "item.components.'minecraft:custom_data'.upgrade[2].value")
161 | var mana = get_data("entity", "@s", "item.components.'minecraft:custom_data'.upgrade[3].value")
162 | var reinforce_cnt = get_data("entity", "@s", "item.components.'minecraft:custom_data'.reinforce_cnt")
163 | /scoreboard players set temp 40planet_num 0
164 | /execute unless data entity @s item.components."minecraft:lore" run scoreboard players set temp 40planet_num 1
165 | /execute if score temp 40planet_num matches 1 run data modify entity @s item.components."minecraft:lore" set value ["{\"color\":\"yellow\",\"italic\":false,\"text\":\"+^reinforce_cnt&강\"}","{\"color\":\"yellow\",\"italic\":false,\"text\":\"체력 ^health&\"}","{\"color\":\"yellow\",\"italic\":false,\"text\":\"근력 ^strength&\"}","{\"color\":\"yellow\",\"italic\":false,\"text\":\"민첩 ^speed&\"}","{\"color\":\"yellow\",\"italic\":false,\"text\":\"마나 ^mana&\"}"]
166 | execute(if score "temp" "40planet_num" matches 0){
167 | /data modify entity @s item.components."minecraft:lore" append value "{\"color\":\"yellow\",\"italic\":false,\"text\":\"+^reinforce_cnt&강\"}"
168 | /data modify entity @s item.components."minecraft:lore" append value "{\"color\":\"yellow\",\"italic\":false,\"text\":\"체력 ^health&\"}"
169 | /data modify entity @s item.components."minecraft:lore" append value "{\"color\":\"yellow\",\"italic\":false,\"text\":\"근력 ^strength&\"}"
170 | /data modify entity @s item.components."minecraft:lore" append value "{\"color\":\"yellow\",\"italic\":false,\"text\":\"민첩 ^speed&\"}"
171 | /data modify entity @s item.components."minecraft:lore" append value "{\"color\":\"yellow\",\"italic\":false,\"text\":\"마나 ^mana&\"}"
172 | }
173 | }
174 |
175 | def success(){
176 | /execute at @s run playsound minecraft:block.anvil.use block @a ~ ~ ~ 1 1
177 | /execute at @s run particle minecraft:happy_villager ~ ~ ~ .5 .3 .5 2 20
178 | reinforce_cnt = reinforce_cnt + 1
179 | /execute align xz run summon text_display ~.5 ~.3 ~.5 {text:'{"text":"+^reinforce_cnt&강","color":"green"}',background:0,shadow:1b,billboard:"vertical",Tags:["reinforce_text","40planet_rpg_entity"]}
180 | set_data("entity", "@s", "item.components.'minecraft:custom_data'.percent", success_per[reinforce_cnt])
181 | set_data("entity", "@s", "item.components.'minecraft:custom_data'.reinforce_cnt", reinforce_cnt)
182 | /execute at @s as @n[tag=reinforce_table] run function __namespace__:update_text
183 |
184 | # 장비별 스텟 추가
185 | execute(if data entity "@s" "item.components.'minecraft:custom_data'.40planet_equipment"){
186 | # 공격력 추가
187 | /scoreboard players set temp 40planet_num 0
188 | /execute if data entity @s item.components.'minecraft:attribute_modifiers'.modifiers run scoreboard players set temp 40planet_num 1
189 | /execute if data entity @s item.components.'minecraft:attribute_modifiers'.modifiers[{type:'minecraft:generic.attack_damage'}] run scoreboard players set temp 40planet_num 2
190 | /execute if score temp 40planet_num matches 1 run data modify entity @s item.components.'minecraft:attribute_modifiers'.modifiers append value {type:"generic.attack_damage",amount:1,slot:mainhand,operation:add_value,id:1524155694201}
191 | /execute if score temp 40planet_num matches 0 run data modify entity @s item.components.'minecraft:attribute_modifiers'.modifiers set value [{type:"generic.attack_damage",amount:1,slot:mainhand,operation:add_value,id:1524155694201}]
192 | execute(if score "temp" "40planet_num" matches 2){
193 | /execute store result score value 40planet_num run data get entity @s item.components.'minecraft:attribute_modifiers'.modifiers[{type:'minecraft:generic.attack_damage'}].amount 10
194 | /execute store result entity @s item.components.'minecraft:attribute_modifiers'.modifiers[{type:'minecraft:generic.attack_damage'}].amount double 0.1 run scoreboard players add value 40planet_num 10
195 | }
196 |
197 | # lore 설정
198 | while(true){
199 | /data remove storage 40planet:rpg temp
200 | /data modify storage 40planet:rpg temp.lore set string entity @s item.components."minecraft:lore"[0] 1 32
201 | /execute unless data storage 40planet:rpg temp{lore:"\"color\":\"yellow\",\"italic\":false"} run return 0
202 | /data remove entity @s item.components."minecraft:lore"[0]
203 | }
204 | /scoreboard players set temp 40planet_num 0
205 | /execute unless data entity @s item.components."minecraft:lore" run scoreboard players set temp 40planet_num 1
206 | /execute if score temp 40planet_num matches 1 run data modify entity @s item.components."minecraft:lore" set value ["{\"color\":\"yellow\",\"italic\":false,\"text\":\"+^reinforce_cnt&강\"}"]
207 | /execute if score temp 40planet_num matches 0 run data modify entity @s item.components."minecraft:lore" prepend value "{\"color\":\"yellow\",\"italic\":false,\"text\":\"+^reinforce_cnt&강\"}"
208 | }
209 | set_score("type", "40planet_num", 0)
210 | /execute if data entity @s item.components.'minecraft:custom_data'.40planet_helmet run scoreboard players set type 40planet_num 1
211 | /execute if data entity @s item.components.'minecraft:custom_data'.40planet_chestplate run scoreboard players set type 40planet_num 2
212 | execute(if score "type" "40planet_num" matches 1..2){
213 | upgrade("health", 1)
214 | }
215 | execute(if data entity "@s" "item.components.'minecraft:custom_data'.40planet_leggings"){
216 | upgrade("strength", 1)
217 | }
218 | execute(if data entity "@s" "item.components.'minecraft:custom_data'.40planet_boots"){
219 | upgrade("speed", 1)
220 | }
221 | execute(if data entity "@s" "item.components.'minecraft:custom_data'.40planet_ring"){
222 | upgrade("mana", 1)
223 | }
224 |
225 | var scrolls = get_data("storage", "40planet:rpg", "scrolls")
226 | # print(scrolls)
227 | var scrolls_len = len(scrolls)
228 | var i = 0;
229 | while(i < scrolls_len){
230 | execute(if data entity "@s" "item.components.'minecraft:custom_data'.40planet_neck"){
231 | upgrade(scrolls[0].type, int(double(scrolls[0].value) * 1.5))
232 | }
233 | execute(unless data entity "@s" "item.components.'minecraft:custom_data'.40planet_neck"){
234 | upgrade(scrolls[0].type, scrolls[0].value)
235 | }
236 | del(scrolls[0])
237 | i = i + 1;
238 | }
239 | }
240 |
241 | def fail(){
242 | execute(at @s align xz positioned "~.5 ~ ~.5"){
243 | /execute as @n[tag=reinforce_table] run function __namespace__:update_text
244 | /playsound minecraft:block.anvil.destroy block @a ~ ~ ~ 1 1
245 | /particle minecraft:angry_villager ~ ~ ~ .3 .1 .3 1 7
246 | }
247 | }
248 |
249 | def destroy(){
250 | execute(at @s align xz positioned "~.5 ~ ~.5"){
251 | /playsound minecraft:entity.generic.explode block @a ~ ~ ~
252 | /particle minecraft:explosion ~ ~ ~ .1 .1 .1 2 5
253 | }
254 | /item replace entity @s container.0 with minecraft:structure_void[minecraft:custom_data={40planet_ui:1b}]
255 | /execute at @s as @n[tag=reinforce_table] run function __namespace__:update_text
256 | }
257 |
258 | def reinforce(){
259 |
260 | /data modify storage 40planet:rpg selected_item set from entity @s item
261 | reinforce_cnt = get_data("storage", "40planet:rpg", "selected_item.components.'minecraft:custom_data'.reinforce_cnt")
262 | execute(unless data storage "40planet:rpg" "selected_item.components.'minecraft:custom_data'.reinforce_cnt"){
263 | reinforce_cnt = 0
264 | }
265 |
266 | set_score("require_level", "40planet_num", reinforce_cnt)
267 | execute(if score "require_level" "40planet_num" matches 25 on passengers){
268 | /execute on target run tellraw @s [{"text":"더 이상 강화할 수 없습니다.","color":"red"}]
269 | /execute on target run playsound minecraft:block.note_block.bass weather @s ~ ~ ~
270 | return 0
271 | }
272 | /execute store result score temp 40planet_num on passengers on target if score require_level 40planet_num <= @s 40planet_level
273 | execute(if score "temp" "40planet_num" matches 0 on passengers){
274 | /execute on target run tellraw @s [{"text":"레벨이 부족합니다. 요구 레벨: ","color":"red"},{"score":{"name":"require_level","objective":"40planet_num"}}]
275 | /execute on target run playsound minecraft:block.note_block.bass weather @s ~ ~ ~
276 | return 0
277 | }
278 |
279 | /execute on passengers on target run xp add @s -^reinforce_cnt& levels
280 | /scoreboard players operation temp 40planet_num = @s 40planet_id
281 | remove_items()
282 |
283 | # 확률 가져오기
284 | execute(at @s as @n[tag=reinforce_table]){
285 | /scoreboard players operation success 40planet_num = @s 40planet_rpg_success_per
286 | /scoreboard players operation fail 40planet_num = @s 40planet_rpg_fail_per
287 | /scoreboard players operation destroy 40planet_num = @s 40planet_rpg_destroy_per
288 | }
289 |
290 | /execute store result score result 40planet_num run random value 1..1000
291 |
292 | # 성공
293 | execute(if score "result" "40planet_num" <= "success" "40planet_num"){
294 | success()
295 | return 0
296 | }
297 | /scoreboard players operation result 40planet_num -= success 40planet_num
298 |
299 | # 실패
300 | execute(if score "result" "40planet_num" <= "fail" "40planet_num"){
301 | fail()
302 | return 0
303 | }
304 |
305 | # 파괴
306 | destroy()
307 | }
308 |
309 | # 강화 작업대 (스크롤 & 강화석으로 장비 강화)
310 | def reinforce_table(){
311 | /scoreboard players operation temp 40planet_num = @s 40planet_id
312 | execute(if block "~ ~-.1 ~" air){
313 | /execute positioned ~ ~-.5 ~ as @e[distance=..0.5] if items entity @s container.0 blackstone run data modify entity @s Item set value {components:{"minecraft:entity_data":{id:"marker",Tags:["40planet_rpg_entity","summon_reinforce_table"]},"minecraft:custom_name":'{"italic":false,"text":"강화 작업대"}'},id:"ender_dragon_spawn_egg"}
314 | /execute on passengers run kill @s
315 | /kill @s
316 | execute(as @e[distance=..0.5,tag=reinforce_table_slot] if score "@s" "40planet_id" = "temp" "40planet_num"){
317 | return_item()
318 | /execute on passengers run kill @s
319 | /kill @s
320 | }
321 | return 0
322 | }
323 | /scoreboard players reset is_weapon_update 40planet_num
324 | /scoreboard players set success 40planet_num 0
325 | /scoreboard players set fail 40planet_num 0
326 | /scoreboard players set destroy 40planet_num 0
327 | execute(as @e[distance=..0.5,tag=reinforce_table_slot] if score "@s" "40planet_id" = "temp" "40planet_num"){
328 | # 아이템 넣기
329 | /scoreboard players set temp 40planet_num 0
330 | /execute on passengers on target run scoreboard players set temp 40planet_num 1
331 | execute(if score "temp" "40planet_num" matches 1){
332 |
333 | # target이 웅크리고 있다면 강화하기 함수 실행하는 코드
334 | execute(if entity @s[tag=reinforce_table_weapon]){
335 | /execute on passengers on target unless predicate rpg:sneaking run return 0
336 | /execute if items entity @s container.0 *[custom_data~{40planet_ui:1b}] run return 0
337 |
338 | reinforce()
339 |
340 | /execute on passengers run data remove entity @s interaction
341 | return 0
342 | }
343 |
344 | /execute on passengers on target run data modify storage 40planet:rpg selected_item set from entity @s SelectedItem
345 | /scoreboard players set temp 40planet_num 0
346 | execute(if entity @s[tag=reinforce_table_weapon]){ # 무기 슬롯인 경우
347 | /execute if data storage 40planet:rpg selected_item.components."minecraft:custom_data".40planet_armor run scoreboard players set temp 40planet_num 1
348 | /execute if data storage 40planet:rpg selected_item.components."minecraft:custom_data".40planet_equipment run scoreboard players set temp 40planet_num 1
349 | }
350 | execute(unless entity @s[tag=reinforce_table_weapon]){ # 강화석, 스크롤 슬롯인 경우
351 | /execute if data storage 40planet:rpg selected_item.components."minecraft:custom_data".40planet_rpg_stone run scoreboard players set temp 40planet_num 1
352 | /execute if data storage 40planet:rpg selected_item.components."minecraft:custom_data".40planet_rpg_scroll run scoreboard players set temp 40planet_num 1
353 | }
354 | /execute on passengers on target unless data entity @s SelectedItem run scoreboard players set temp 40planet_num 0
355 |
356 | execute(if score "temp" "40planet_num" matches 1){
357 | /execute on passengers on target run item modify entity @s weapon rpg:weapon_minus
358 | # 이미 다른 아이템이 있으면 돌려주기
359 | target_attack = "target"
360 | /execute unless items entity @s container.0 *[minecraft:custom_data~{40planet_ui:1b}] run function __namespace__:return_item
361 |
362 | /data modify storage 40planet:rpg selected_item.count set value 1
363 | /data modify entity @s item set from storage 40planet:rpg selected_item
364 |
365 | /scoreboard players set is_weapon_update 40planet_num 1
366 | }
367 |
368 |
369 | /execute on passengers run data remove entity @s interaction
370 | }
371 |
372 | # 아이템 빼기
373 | /scoreboard players set temp 40planet_num 0
374 | /execute on passengers on attacker run scoreboard players set temp 40planet_num 1
375 | /execute if items entity @s container.0 *[custom_data~{40planet_ui:1b}] run scoreboard players set temp 40planet_num 0
376 | execute(if score "temp" "40planet_num" matches 1){
377 | target_attack = "attacker"
378 | return_item()
379 | /execute on passengers run data remove entity @s attack
380 |
381 | /scoreboard players set is_weapon_update 40planet_num 1
382 | }
383 | }
384 |
385 | # 무기 슬롯에 변화가 없었다면 종료
386 | /execute unless score is_weapon_update 40planet_num = is_weapon_update 40planet_num run return 0
387 | update_text()
388 | }
--------------------------------------------------------------------------------