├── 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 | 3 | 4 | -------------------------------------------------------------------------------- /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 | 3 | 4 | -------------------------------------------------------------------------------- /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 | 3 | 4 | -------------------------------------------------------------------------------- /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 | 3 | 4 | -------------------------------------------------------------------------------- /web/image/global.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | 3 | 4 | -------------------------------------------------------------------------------- /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 |
17 |
18 |
19 |
20 |
21 | 22 | Select file to compile 23 |
24 | 25 |
26 | 27 | 28 |
29 |
30 |
31 |
32 | 33 | Select folder to locate output 34 |
35 | 36 |
37 | 38 | 39 |
40 |
41 | 42 | Select minecraft version 43 | 56 |
57 |
58 | 59 | Input namespace. Capitalized character will be force-lowercased. 60 | 61 |
62 |
63 | 64 | 69 |
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 | } --------------------------------------------------------------------------------