마붕이들은 이런 기억이 있을 거임.
만약 다른 엔티티들로 하여금 다른 행동을 하도록 시킬 때, 그런데 그 엔티티들이 어딘가 공통점이 있을 때...
아래의 예시는 엔티티들이 매우 간간간간고등어하게 위협하는 코드임. (아이 물어워라)
execute as @e[type=zombie] run mob:zombie_threat :
say @a 마플 키는 169.9다 크어어어어
execute as @e[type=skeleton] run mob:skeleton_threat :
say @a say @a 마플 키는 169.9다 덜그럭 덜그럭
지금은 두 가지 종류가 전부지만, 프로젝트가 커지면 다른 태그를 가진 엔티티들을 execute if나 execute as로 분리해서 써내려가야하는 매우 간고등어 같은 일이 벌어지게 될 것임.
그냥 execute as @e[tag = <supertype>] run 해서 한 루프 안에 모든 것을 끝낼 수 없을까?
$function $(function)
$function isa:call with storage minecraft:vtable list[$(entityID)][$(vtableID)]
방법이 있음! 위 매크로 두 개만 있으면 된다.
먼저 아래와 같이 초기화를 해 준다.
scoreboard objectives add register dummy
scoreboard objectives add vtableID dummy
scoreboard players set #lastID vtableID 0
data modify storage minecraft:vtable list set value []
그리고 다음과 같이 좀비와, 스켈레톤을 제작해 준다.
summon minecraft:zombie ~ ~ ~ {Tags:["new"]}
execute as @n[tag=new] run scoreboard players set @s entityID 1
execute unless data storage minecraft:vtable list[1] run \
data modify storage minecraft:vtable list append value [{function:"test:zombie_say"}, {function:"test:zombie_death"}]
execute if data storage minecraft:vtable list[1] run \
data modify storage minecraft:vtable list[1] set value [{function:"test:zombie_say"}, {function:"test:zombie_death"}]
execute as @n[tag=new] run tag @s remove new
summon minecraft:skeleton ~ ~ ~ {Tags:["new"]}
execute as @n[tag=new] run scoreboard players set @s entityID 0
execute unless data storage minecraft:vtable list[0] run \
data modify storage minecraft:vtable list append value [{function:"test:skeleton_say"}, {function:"test:skeleton_death"}]
execute if data storage minecraft:vtable list[0] run \
data modify storage minecraft:vtable list[0] set value [{function:"test:skeleton_say"}, {function:"test:skeleton_death"}]
execute as @n[tag=new] run tag @s remove new
여기서 눈치 빠른 사람들은 저 위의 function:"test:skeleton_say"가 함수 이름인 것을 확인했을 거임. 저 값이 매크로를 통해 전달되고 전달되어서 마침내 함수 호출로 이어지게 될 거임.
execute unless score #op0 register matches -2147483648..2147483647 \
run return run say #op0 register 를 설정해 주세요.
execute unless score #op1 register matches -2147483648..2147483647 \
run return run say #op1 register 를 설정해 주세요.
data modify storage minecraft:temp val set value {entityVTableID : -1, vtableID : -1}
execute store result storage minecraft:temp val.entityID int 1 run scoreboard players get #op0 register
execute store result storage minecraft:temp val.vtableID int 1 run scoreboard players get #op1 register
function isa:call_vtable/call_with_table with storage minecraft:temp val
#$function isa:call with storage minecraft:vtable list[$(entityID)][$(vtableID)]
#data remove storage minecraft:temp val
scoreboard players reset #op0 register
값 두 개 (entityID, vtableID)를 받아서 정말 함수를 호출하는 코드까지 짜고 나서
function test:say :
execute unless score @s entityID matches -2147483648..2147483647 run return 1
scoreboard players operation #op0 register = @s entityID
scoreboard players set #op1 register 0
execute as @s run function isa:call_vtable
위와 같은 코드를
다음과 같이 실행하면
이렇게 출력이 된다.
마붕이들도 코드를 적게 수정하면서 많은 기능을 추가하는 생산적인 하루 되길 바란다.
예제 코드는 첨부파일로 올려 놓았으니 씹고 뜯고 맛보고 즐기면 되겠음.
추가적으로 해당 코드는 엔티티 타입이 2 개만 있다고 가정하고 만든 예싱 데이터팩임... 아마 이걸 프로젝트에 바로 적용하려면 수정을 좀 많이 가해야 할 거임. 관련해서는 나중에 또 글을 올리겠음.
그리고 원리적으로는 엔티티의 ID를 통해서 vtable의 위치를 찾는 것이 아니라, 엔티티의 타입ID를 통해서 vtable의 위치를 찾는 것이 원칙임. (그리고 그걸 프로그래밍 언어에서는 class라고 함. ㅇㅇ 그 클래스 맞음) 해당 변수명이 저 꼴이 된 것은 전적으로 글쓴이의 탓이니 그리 알면 되겠음 (이런 간간간ㄴ간고등어같은)
댓글 0