응 아니야

안녕하세요. 당이천입니다.

 

4장에서는 attribute에 대해서 알아봅니다. 1.16(20w17a)에서 추가된 명령어로, 사전적 의미처럼 엔티티가 가진 '특성'을 반환하거나 바꿀 수 있는 명령어입니다. 이 엔티티에는 플레이어도 포함됩니다.

 

/attribute [대상] [특성] [base/get/modifier] [get/set|add/remove/value]

 

1. 대상

대상으로는

@a 모든 플레이어

@e 엔티티

@p 가까운 플레이어

@r 무작위 플레이어

@s 본인

직접입력(이름)

까지 흔히 보아왔던 대상선택인자가 있습니다.

 

2. 특성

특성으로는 아래 보시는 것처럼 13가지가 있습니다.

 

특성 기능 최대값
minecraft:generic.armor 방어력 30
minecraft:generic.armor_toughness 방어 강도 20
minecraft:generic.attack_damage 공격력 2048
minecraft:generic.attack_knockback 밀치기 강도(플레이어는 적용 안됨) 5
minecraft:generic.attack_speed 공격 쿨다운 1024
minecraft:generic.flying_speed 비행 속도(날 수 있는 엔티티) 1024
minecraft:generic.follow_range 플레이어를 따라오는 개체의 인식 범위 2048
minecraft:generic.knockback_resistance 밀치기 저항(1.0당 100%) 1
minecraft:generic.luck 행운 1024
minecraft:generic.max_health 최대체력 1024
minecraft:generic.movement_speed 이동속도(플레이어는
0.10000000149011612)
1024
minecraft:horse.jump_strength 말의 점프력 2
minecraft:zombie.spawn_reinforcements 좀비 공격 시 친구 소환 확률(1.0=100%) 1

3. 동작

 

3-1. base

base는 해당 엔티티가 가진 특성의 기초값을 말합니다.

base가 선택된 경우에는 get/set 중 하나를 선택하여야합니다.

  get을 선택하면 base 값을 반환합니다.

  set을 선택하면 base 값을 설정할 수 있습니다. 값은 숫자이며 자료형은 double입니다. (실수)

/attribute @s minecraft:generic.armor_toughness base get

당이천 개체의 방어 강도 특성 기초 값은 0.0입니다.

 

3-2. get

get은 기초값+추가된 값의 합을 입력한 scale 값에 곱해서 반환합니다.

말이 어렵습니다. 풀어서 설명해보겠습니다.

a. 기초값

이란 엔티티가 처음부터 가지고 생성되는 값입니다.

b. 추가된 값

이란, 방어구나 인첸트 또는 물약효과 등 외부적인 요인으로 인해서 언제든 변할 수 있는 값을 말합니다.

이 두가지 값을 합한 값이 base를 넣지 않은 get의 결과값입니다.

즉, 플레이어의 기초 방어 강도 값은 0이고 맨몸인 경우 base를 넣지 않고 get을 입력하더라도 결과값은 0입니다.

 

c. '방어 강도'라는 값이 붙기 시작하는 다이아몬드 갑옷을 입어봅니다.

표기상 +2이므로, base get의 결과는 0.0 그대로이고, get의 결과는 2.0이 맞습니다. 확인해보겠습니다.

/attribute @s minecraft:generic.armor.toughness get

예. 맞습니다. 2.0이라는 값을 반환했습니다.

엔티티 그 자체가 가진 기초 값을 반환 받으려면 base를 앞에 넣고

그렇지 않은 경우에는 base를 빼고 get만 넣으면 된다는 것입니다.

 

3-2-1. scale

위에서 짧게 언급이 있었습니다. 스케일 값은 결과값을 뻥튀기 시켜주는 인자입니다.

반환할 값이 2.0이고, scale 값에 2를 입력한 경우 반환할 값은 곱해져서 4.0이 되는 인자인 것입니다.

하지만! 적용이 안 됩니다. 이 스케일 값은 단순 입력으로 반환할 수 없는 인자이기 때문입니다.

반환할 필요 조차 없죠. 데이터팩이나 명령블록으로 일련의 동작들을 구현했을 때 비로소 필요한 인자입니다.

스코어보드에 넣어야 적용이 됩니다.

 

이것 역시 확인해보겠습니다.

/scoreboard objectives add scale dummy

더미 목표로 스케일이란 이름의 스코어 보드를 만들어줍니다.

/scoreboard objectives setdisplay sidebar scale

스케일이란 이름의 스코어 보드를 사이드바(화면 우측)에 표시토록 합니다.

/scoreboard players set @s scale 0

값을 0으로 설정하여 값이 있어야만 표시되는 스코어보드가 작동하도록 합니다. (이때부터 보임)

/execute store result score @s scale run attribute @s minecraft:generic.armor_toughness get 2

1.스케일 값을 2로 설정하여 반환합니다.

다이아몬드 흉갑을 입고있으므로 방어 강도 특성 값은 2.0인 상태입니다.

2. 반환된 값 2라는 결과를 스케일이라는 이름의 스코어보드에 store(여기서는 저장)합니다.

확인해볼까요?

예. 명령어는 길어서 잘렸지만 아무튼 스코어보드에 4라는 값이 출력됨을 보실 수 있습니다.

 

실제 저장된 값은 0.0과 2.0으로써 get 하더라도 2.0으로 변함없습니다. 스케일을 통해서 스코어보드 같은 저장매체에 넣으면 특성값은 그대로이지만 4라는 integer 값으로 잘 저장됨을 알 수 있습니다. 이 스케일을 이용해서 특정 시간동안만, 특정 행동을 하는 동안만 특성을 뻥튀기 시켜주는 기능을 만들어볼 수 있겠습니다. 이건 모장이 좋아하는 창의력 대장에게 맡겨두고 다음 설명으로 넘어가겠습니다.

 

3-3. modifier

modifier 수정자라 번역합니다. 1.20.1에서는 변경자로 번역합니다. 간단히 '선택한 특성에 값을 추가하는 기능'이라고 생각하시면 됩니다.

 

base 인자에는 get과 set이 있었으므로 set을 선택하여 base 값을 바꾸면 되었는데, base와 같은 열에 있는 것은 get과 modifier뿐이었습니다. 즉 modifier는 set이라고 봐야합니다.

 

다만 그 값을 세세하게 조정할 수 있는 아주 좋은 기능이라고 볼 수 있습니다.

(거꾸로 얘기하면 아주 귀찮다입니다.)

 

이번에도 역시 방어 강도를 기준하여 설명합니다.

 

modifier add uuid name value add,multiply,multiply_base

modifier remove uuid

modifier value get

 

modifier 밑에는 add, remove, value라는 인자가 있습니다. 추가 제거 그리고 값 반환입니다.

우리는 modifier로 값을 추가한 적이 없으니 먼저 추가부터 해보겠습니다.

 

a. ADD

add 아래에는 다시 uuid name value라는 인자가 있고, 다시 value에 있는 값을 연산할 수 있는 add, multiply, multiply_base라는 인자가 있습니다. 하나도 빼먹을 수 없습니다. 썼으면 끝까지 써야합니다.

 

 

UUID

uuid란 고유식별번호입니다. 컴퓨터로 통틀어서 얘기하자면 통신규약입니다. 마크에선 그냥 데이터 저장용 식별번호로 쓰입니다. 중복될 수 없도록 뒤지게 많은 숫자를 사용하며 구분기호와 구분점을 미리 짝짝꿍 맞추고 전세계 사람이 똑같은 방식으로 사용하는 것이죠.

 

16진수으로 표현하며 5번 끊고 끊어지는 곳은 하이픈(붙임표)이라 불리는 빼기(-) 문자열로 채웁니다. 즉 아래와 같습니다.

 

0-0-0-0-1

 

구분점마다 지정된 자릿수가 있습니다.

8-4-4-4-12 총 32자리 숫자입니다.

우리가 익히 봐왔던 그 UUID가 맞습니다.

 

069a79f4-44e9-4726-a5be-fca90e38aaf5

 

노치의 uuid입니다.

 

uuid를 입력할 때 자릿수를 채우지 않아도 됩니다.

 

0-0-0-0-1이라고 입력하더라도 앞에 0을 자동으로 채워주기 때문입니다.

 

다만 기억하기도, 구분하기도 쉽도록 특정 자릿수에 나를 상징하는 숫자를 넣고 해당 기능을 상징하는 숫자를 넣고 차례대로 숫자를 넣는 방식이면 좋겠죠.

 

아무튼 uuid로 구분하여 방어 강도에 값을 추가하여 변경해보도록 하겠습니다.

 

저는 구분을 위해서 '당이천'이라는 문자열을 16진수로 변환하여 eb8bb9ec9db4ecb29c라는 값을 얻었고, 이 값을 uuid 앞에 박아서 구성해보겠습니다.

 

/attribute @s minecraft:generic.armor_toughness modifier add eb8bb9ec-9db4-ecb2-9c00-00000000

18자리이므로 8-4-4-4(2+00)-8 9c 뒤에는 00으로 채우고 마지막 8자리는 임의로 0부터 1씩 올리도록 하겠습니다.

 

name

/attribute @s minecraft:generic.armor_toughness modifier add eb8bb9ec-9db4-ecb2-9c00-00000000 test

uuid를 채웠으니 이름(name)이 필요합니다. 저는 test로 합니다. nbt에는 Name에 기록됩니다.

 

value

이름을 채웠으므로 값(value)이 필요합니다. 저는 2로 합니다. nbt에는 Amount에 기록됩니다.

/attribute @s minecraft:generic.armor_toughness modifier add eb8bb9ec-9db4-ecb2-9c00-00000000 test 2

 

operator

별다른 연산 없이 2 그대로 넣을 것이라서 add로 마무리합니다.

/attribute @s minecraft:generic.armor_toughness modifier add eb8bb9ec-9db4-ecb2-9c00-00000000 test 2 add

 

uuid 변경자에 맞게 값이 추가됐습니다.

그렇다면 지금 저의 방어 강도는 몇일까요? 당연히...

 

기초값 0.0, 다이아몬트 흉갑 2, 방금 추가한 변경자값 2로

4.0입니다.

 

위에서 operator에는 add multiply multiply_base가 있다고 했습니다.

add는 값을 더합니다.

multiply_base는 1base+값을 곱합니다.

multiply는 1+값을 곱합니다.

 

까지가 다른 블로그나 사이트에서 다룬 내용일 것입니다.

여기까지만 알면 '아! 값을 추가하고 제거하고 조회할 수 있구나' 정도로 넘기게 됩니다.

하지만 정수는 여기서부터 시작합니다.

 

중요한 것이 남았기 때문입니다.

첫째로는 uuid 앞의 add로 값들을 추가할 때 여러번 할 수 있다는 것입니다. (그래서 uuid를 썼잖아요?)

둘째로는 값이 여럿일 때 계산식이 조금은 특이하다는 것입니다.

 

여러번 추가하여 계산해보겠습니다. 방어강도는 최대값이 20이어서 너무 낮은 관계로 attack_damage로 변경합니다.

 

연산자 add

 

먼저 더하기부터 합니다.

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000000 test 2 add

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000001 test 4 add

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000002 test 8 add

 

맨손일 경우 base는 1 합은 15입니다. (1+2+4+8)

공격 피해 4인 나무 검을 든 경우 base는 1 합은 18입니다. 4+(2+4+8)

공격 피해 5인 돌 검을 든 경우 base는 1 합은 19입니다. 5+(2+4+8)

공격 피해 6인 철 검을 든 경우 base는 1 합은 20입니다. 6+(2+4+8)

공격 피해 7인 다이아몬드 검을 든 경우 base는 1 합은 21입니다. 7+(2+4+8)

공격 피해 8인 네더라이트 검을 든 경우 base는 1 합은 22입니다. 8+(2+4+8)

 

연산자 multiply_base

 

이번엔 더하기했던 값을 모두 지우고

multiply_base 기초값 곱하기를 해보겠습니다.

 

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000000 test 2 multiply_base

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000001 test 4 multiply_base

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000002 test 8 multiply_base

 

맨손일 경우 base는 1 합은 15입니다. (1+2+4+8)

공격 피해 4인 나무 검을 든 경우 base는 1 합은 60입니다. 4*(1+2+4+8)

공격 피해 5인 돌 검을 든 경우 base는 1 합은 75입니다. 5*(1+2+4+8)

공격 피해 6인 철 검을 든 경우 base는 1 합은 90입니다. 6*(1+2+4+8)

공격 피해 7인 다이아몬드 검을 든 경우 base는 1 합은 105입니다. 7*(1+2+4+8)

공격 피해 8인 네더라이트 검을 든 경우 base는 1 합은 120입니다. 8*(1+2+4+8)

 

연산자 multiply

 

이번엔 base 곱했던 값을 모두 지우고

곱하기를 해보겠습니다.

 

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000000 test 2 multiply

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000001 test 4 multiply

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000002 test 8 multiply

 

맨손일 경우 base는 1 합은 135입니다. (1+2)*(1+4)*(1+8)

공격 피해 4인 나무 검을 든 경우 base는 1 합은 540입니다. 4*(1+2)*(1+4)*(1+8)

공격 피해 5인 돌 검을 든 경우 base는 1 합은 675입니다. 5*(1+2)*(1+4)*(1+8)

공격 피해 6인 철 검을 든 경우 base는 1 합은 810입니다. 6*(1+2)*(1+4)*(1+8)

공격 피해 7인 다이아몬드 검을 든 경우 base는 1 합은 945입니다. 7*(1+2)*(1+4)*(1+8)

공격 피해 8인 네더라이트 검을 든 경우 base는 1 합은 1,080입니다. 8*(1+2)*(1+4)*(1+8)

 

특정 아이템을 착용/소지한 경우를 감지하여 변경자(modifier)를 수정함으로써 플레이어의 능력을 강화하는 서버를 만들 계획이시라면.. 알고계시는 것이 좋습니다.

 

b. remove

remove는 이름대로 제거입니다. 이전에 입력했던 변경자를 제거하는 인자죠. 하위 인자랄 것은 없고, 들어가야하는 값은 있습니다. UUID 입니다. add로 추가할 때 썼던 uuid를 입력하면 제거할 수 있습니다.

 

/attribute @s minecraft:generic.attack_damage modifier remove UUID

/attribute @s minecraft:generic.attack_damage modifier remove 0-0-0-0-0

 

문제는 규모가 있는 뭔가를 만들다 보면 uuid 갯수도 많아지고 외우기 힘들다는 것입니다. 모든 엔티티의 모든 uuid를 외울 수는.. 없죠? 메모장에라도 정리해뒀다면 꺼내볼 수 있겠지만, 그렇지 않은 경우에 기억해내기란 쉽지 않을 것입니다. 제가 그렇습니다.

 

uuid, name, value, operator 모두를 조회할 방법이 있습니다.

/data 명령어로 엔티티의 nbt를 읽는 것입니다.

 

아직 제 블로그에서는 다루지 않은 명령어입니다.

따로 설명은 안 하고 완성된 명령어를 알려드리고 넘어가겠습니다.

게시물로 따로 다룰테니까요.

 

/data get entity @s Attributes

 

사진에는 값이 없습니다. 넣었다가 지웠거든요. 저것이 평시 모습에 가깝습니다. 특히 플레이어요.

 

이번 사진은 값을 다시 추가해서 찍었습니다.

 

/attribute @s minecraft:generic.attack_damage modifier add eb8bb9ec-9db4-ecb2-9c00-00000000 test 2 add

 

위 명령어로 넣은 것입니다.

 

[{Base: 1.0d, Modifiers:[{Amount: 2.0d, Operation: 0, UUID: [I: -343164436, -1649087310, -1677721600, 0], Name: "test"}], Name:"minecraft:generic.attack_damage"}]

 

정리하면 아래와 같습니다. 이동속도는 생략합니다.

 

[
   {
      "Base":1.0d,
      "Modifiers":[
         {
            "Amount":2.0d,
            "Operation":0,
            "UUID":[
               "I":-343164436,
               -1649087310,
               -1677721600,
               0
            ],
            "Name":"test"
         }
      ],
      "Name":"minecraft:generic.attack_damage"
   }
]

 

하나씩 풀어보겠습니다.

 

Base 1.0

무기나 도구 없이 맨손일 경우 데미지 값입니다. base set 인자를 사용해서 값을 바꿨을 때 이 값이 바뀌고, 곱연산을 했을 때 이 값의 영향을 받게 되는 것입니다.

 

Modifiers

 

Amount 2.0

test 뒤에 입력한 2가 이 값입니다. 명령어 입력 시 입력 창 위에 뜨기로는 <value>라고 뜹니다. 입력된 이후에는 Amount로 저장됩니다.

 

Operation 0

오퍼레이션. 연산자가 자정되는 부분입니다. add(multiply, multiply_base) 부분이 바로 이 값이 됩니다.

add는 0이고, multiply_base는 1이고, multiply는 2입니다. 명령어 추천으로는 문자열 정렬 때문에 1,2번 순서가 뒤틀렸지만 아무튼 그렇습니다.

 

UUID

"I":-343164436, -1649087310, -1677721600, 0

이렇게 저장되었습니다. 분명 입력한 값은 eb8bb9ec-9db4-ecb2-9c00-00000000인데 말입니다.

입력한 값은 하이픈으로 구분한 16진수 uuid이고, 저장된 값은 정수배열로 변환한 uuid입니다.

데이터 처리 속도 문제로 값을 변환하여 저장한다고 합니다.

 

uuid를 기억하지 못한다고 nbt를 읽어왔더니 변환된 uuid가 저장되어 있다. 즉, '봐도 읽을 수 없다' 입니다.

변환기 사이트 링크를 알려드립니다. 즐겨찾기(북마크) 추가해두시고 사용하세요.

 

https://www.soltoder.com/mc-uuid-converter/

 

Minecraft UUID Converter

 

www.soltoder.com

 

(참고로 Most, Least 값은 1.16 이전에 사용된 uuid 방식입니다. 1.16부터는 사용하지 않습니다.)

 

Name: test

네.. 입력한대로 test가 들어갔습니다.

 

c. value

변경자로 추가(add)한 uuid마다 저장된 값이 있지 않습니까? value라고 부르지만 Amount로 저장됐던 그 값. 그 값을 조회하는 인자입니다.

 

하위 인자로 get이 있습니다.

 

/attribute @s minecraft:generic.attack_damage modifier value get UUID scale

 

조회할 uuid를 입력하면 nbt에 저장된 Amount의 값을 조회할 수 있습니다.

scale은 get/base get에서 보았던 것과 같이 반환값을 뻥튀기 시킬 때 사용하면 됩니다.

 

하나씩 다 알아봤는데 역시 쓰다보니 내용이 길어지고 정리가 잘 안 된 느낌도 듭니다. 게다가 티스토리 성능이 구린지 글쓰기 내용이 길어지면 5초마다 화면이 끊기는 문제가 있네요.

 

아무튼 base부터 modifier까지 알아봤습니다.. 일단 여기서 마치고 게시합니다. 잘못된 부분이나 미흡한 부분은 게시 이후에 다시 읽어보면서 수정하겠습니다.

 

감사합니다.

공유하기

facebook twitter kakaoTalk kakaostory naver band