하이픽셀 같은 로비 메뉴 만들어보기 > 트리거 심화

본문 바로가기
사이트 내 전체검색


트리거 심화

하이픽셀 같은 로비 메뉴 만들어보기

페이지 정보

작성자 wysohn 작성일19-05-12 13:20 조회795회 댓글0건

본문

요구 지식: 인벤토리 트리거, 네임드 트리거

일단 시작하기에 앞서서 하이픽셀같은 로비 메뉴를 만드려면 몇가지 준비가 필요합니다.

0. 탬플릿
---
탬플릿을 사용하는건 어디까지나 이해를 쉽게 하기 위함이고 자신만의 구성을 하고 싶다면 궂이 사용하지 않아도 됩니다. 하지만
기본적으로 이런식으로 코드를 짜는게 매우 편리합니다.

IF trigger == "open"

ENDIF

IF trigger == "click"
    IF slot == 10
        #MESSAGE "11번 째 슬롯을 클릭 함"
    ENDIF
ENDIF

이미 위키를 보시는것에 조금 익숙한분들은 아시겠지만 여기서 trigger라는 변수는 인벤토리 트리거 자체에서 제공하는 변수로
해당 인벤토리에서 어떤 이벤트가 발생 했는지 말해줍니다. open은 직역해서 말그대로 인벤토리를 처음 연 그 순간을 말하는것이고
click은 인벤토리 내의 아이템중 하나를 클릭 한 경우를 말합니다. (참고: click의 경우 빈 공간을 클릭 해도 작동합니다.)

또 IF trigger == "click" 아래에 보면 slot이라는 변수가 존재하는데 이 역시 인벤토리 트리거에서 자체적으로 제공하는 변수로
click 이 발생했다는 조건 하에서 이 slot에는 몇번째 칸에 있는 아이템이 클릭 되었는지 정수값으로 들어가게 됩니다.
이미 생성 명령어에서 보셨다시피 인벤토리는 총 9개의 칸이 최대 6줄 까지 가능 한 구조로 맨 윗줄이 0~8, 그 다음이 9~17, ... 이런식으로
53까지 가능합니다. 여기서 왜 9*6은 54인데 왜 53까지인가 묻는 분들이 있을 수 있는데 이는 슬롯이 0번부터 시작하기 때문에 1이 빠지게
되는 것 입니다.

1. 인벤토리 디자인
---
먼저 메뉴를 구성하기 전에 디자인을 어떤식으로 할 지 정해야 할 것 입니다. 저는 디자인에는 그다지 소질이 없기 때문에
그냥 인벤토리 왼쪽부터 오른쪽으로 쭉 버튼을 대충 하나씩 넣는것으로 채용 하겠습니다.

1-1. 손에 들고있는 아이템을 이용하는 방법
이 방법은 코딩이 필요없이 손에 들고있는 아이템을 넣을 수 있는 기능으로 편리하게 버튼을 추가 하고싶다면 추천 합니다.

/trg i <이름> item <슬롯>

이 명령어를 치는 경우 현재 손에 들고있는 아이템이 <이름> 인벤토리 트리거의 <슬롯> 번 째 슬롯에 등록 되게 됩니다.
예를들어 /trg i myMenu item 0 이라고 친다면 손에 들고있는 아이템이 myMenu 인벤토리거의 0번째 슬롯에 등록 됩니다.
만약 아무것도 들고있지 않은 상태에서 사용 한다면 해당 슬롯에 이미 존재하는 아이템이 삭제 됩니다.

2-2. 코드로 직접 집어넣는 방법
이 방법을 사용하면 조금 더 복잡하지만 다양한 작업을 수행 할 수 있게됩니다. 인벤토리 트리거에서 제공하는 inventory 변수는 인벤토리
자체에 직접 접근을 가능하게 해주는 변수로 초보자라면 setItem(슬롯, 아이템) 만 알아도 왠만해서는 큰 문제 없이 사용이 가능 합니다.

setItem의 경우 슬롯은 숫자이고 아이템은 ItemStack입니다. ItemStack의 경우 item() 을 이용할 수 도 있고 광역변수를 사용해도 될것입니다.

예제)
IF trigger == "open" // 당연하게도 인벤토리가 열릴때 넣는것이 가장 합리적이겠죠?
    inventory.setItem(0, item("DIAMOND_SWORD", 1))
    inventory.setItem(1, {"myItem"})
ENDIF

1-end.
위에서 상기한 방법 대로 자유롭게 인벤토리 디자인을 구성 해 보세요. 구성이 끝났다면 클릭시 작업을 구현 해봅니다.

2. 메뉴 클릭 구현
---
위에서 한 방법대로는 메뉴는 생성 했으나 클릭시에 아무런 반응이 없게 됩니다. 왜냐하면 아직 아무런 기능도 구현되어있지 않기 때문이지요.

위의 탬플릿을 그대로 복붙해오면:

IF trigger == "click"
    IF slot == 10
        #MESSAGE "11번 째 슬롯을 클릭 함"
    ENDIF
ENDIF

이러한 모양새가 됩니다.

아마 이미 1. 에서 슬롯에 아이템을 넣었을테니 이제 조금 수정을 해봅시다.

IF trigger == "click"
    IF slot == 0
        #MESSAGE "0번 째 슬롯을 클릭 함"
        #SERVER "HCF"
    ENDIF
ENDIF

저의 경우 0번째 슬롯에 /trg i myMenu 0 으로 아이템을 넣었다는 가정하에 코드를 짰으므로 제가 손에 들고있던
아이템이 0번째 칸에 보이게 될 것 입니다. 이제 이것을 클릭 하면 "0번 째 슬롯을 클릭 함" 이라는 메시지가 나오고
그 후에 HCF라는 서버 (번지코드 환경에서 /server HCF 하는것과 같은 효과) 로 이동 됩니다.

쉽죠?

3. 메뉴 꾸미기
---
하이픽셀의 경우 아이템이 단순히 다이아 검 이 아니고 아이템의 설명칸에 서버 인원수나 애니메이션등이 실시간으로 바뀝니다.
비슷한것을 우리도 TRG로 구현해봅시다.

3-1. 네임드 트리거 만들기
이 항목은 필수는 아니지만 해두면 이후에 매우 편리합니다.

먼저 반복되는 작업을 간략화 하기 위해 네임드 트리거를 하나 만들겠습니다. NamedTriggers 폴더 안에 menu 라는 폴더 안에
updateitem.trg 라는 파일을 수동으로 생성 한 뒤 내용물을 메모장으로 아래처럼 수정 했습니다:

//시작
setItemTitle(item, title)
addLore(item, placeholder.parse(player, "&7상태&8: &6%pinger_isonline_127.0.0.1:"+port+"%"))
addLore(item, placeholder.parse(player, "&7접속자 수&8: &6%pinger_players_127.0.0.1:"+port+"%"))
addLore(item, placeholder.parse(player, "&7버전&8: &61.8.8~1.13.2"))
addLore(item, "")
IF blink
addLore(item, color("&a➤ 클릭 시 이동"))
ELSE
addLore(item, color("&8➤ 클릭 시 이동"))
ENDIF
inventory.setItem(targetSlot, item)
//끝

여기서 조금 복습을 하자면 네임드 트리거의 경우 이 네임드 트리거를 #CALL 한 트리거와 변수를 모두 공유합니다. 즉 여기서 item 이나 inventory등은 #CALL을 한 트리거에서 미리 지정을 해줘야 한다는 것 이지요. 아시다시피 inventory의 경우 이미 인벤토리 트리거에서 제공 하기때문에 여기서는
필요해지는게 title, port, item, blink,targetSlot 이렇게 5개 정도가 되겠습니다.

조금 코드를 분석 해보자면
1) setItemTitle()의 경우 첫번째 인자로 오는 아이템 (item) 의 이름을 title 로 바꾸라는것이고
2) addLore도 같은 맥락으로 첫번째 인자로 오는 아이템의 lore에 두번째 인자에 오는 값을 추가 하라는 것 이고
3) IF blink 문의 경우 blink 가 true면 초록색으로 "➤ 클릭 시 이동"를 넣고 아니라면 회색으로 "➤ 클릭 시 이동" 를 넣으라고 되어있습니다.
4) 그리고 마지막에는 inventory.setItem()으로 targetSlot 위치에 해당 아이템을 집어 넣는것이구요.

이제 네임드 트리거는 완성했으니 인벤토리 트리거로 다시 돌아갑니다.

3-2. 실시간으로 아이템 정보 업데이트 하기

이제 다시 IF trigger == "open" 으로 돌아갑니다.

여기서 한가지 먼저 설명을 드리자면 인벤토리 트리거의 경우 매우 특수한 규칙이 적용되는데 다른 트리거와 달리 인벤토리 트리거는
인벤토리가 열려있는 동안만 트리거가 실행이 됩니다. 물론 실행이 한번만 되는 코드의 경우 이게 무슨 소용이 있는가 하겠지만 무한 반복문을
쓴다면 이야기가 달라집니다. 아시다시피 트리거 내에서 WHILE true 등으로 무한 반복문을 쓰는건 매우 위험하다고 알려져 있고 또한 사실이지만
이것은 일반적인 트리거의 경우 한번 실행이 되면 더이상 중간에 작동을 멈출 수 없기 때문입니다. 인벤토리 트리거의 경우 예외적으로 무한 반복문을
쓰더라고 위에서 말했다시피 인벤토리가 열려있는 동안만 트리거가 실행 되기 때문에 무한반복문이 실행중이라고 해도 인벤토리를 닫는 순간
무한반복문도 포함해서 트리거가 종료되게 됩니다. 이 점을 이용해서 실시간으로 업데이트 되는 메뉴를 만들어 봅시다.

IF trigger == "open" // 인벤토리가 최초에 열릴때만 실행하게
    blink = false // 위에서 만든 네임드 트리거에서 사용을 위해 먼저 false로 설정 해둡니다.
    IF placeholder // PlaceHolderAPI가 작동중인지 확인합니다. 없다면 무의미하겠죠?
        address = "127.0.0.1" // 서버 주소. 주로 자기 자신을 뜻하는 127.0.0.1을 사용합니다.

        glass = item("STAINED_GLASS_PANE", 1) // 스태인드 글래스 아이템을 만듭니다.
        setItemTitle(glass, color("&f")) // 스태인드 글래스의 이름을 빈공간으로 설정
                FOR i = 0:45 // 인벤토리 모든칸을 glass 로 채웁니다
                        inventory.setItem(i, glass)
                ENDFOR

                WHILE true // 여기가 바로 무한반복문!
                        targetSlot = 10 // 네임드 트리거에서 사용할 변수. 슬롯 10
                        port = "25501" // 해당 서버 포트 번호
                        title = color("&6HCF &8(&c하드코어 팩션&8)") // 아이템 이름 설정
                        item = item("DIAMOND_SWORD", 1) // 다이아 검 아이템 생성
                        #CALL "menu:updateitem" // 이 부분이 바로 네임드 트리거를 사용하는 부분.
                                                                    // 이 네임드 트리거 실행이 끝나면 내용물이 바뀌어 있을겁니다.

                        #WAIT 1 // 1초의 딜레이를 줍니다. 너무 빨리 반복문이 돌아가면 애니메이션이 고장납니다. 1초 이상이 적절
                        blink = !blink // blink가 true 면 false로 그리고 false면 true로 반복문이 진행 할때마다 바꿔줍니다.
                                              // 이렇게 해야 updateitem 네임드 트리거의 IF문이 번갈아 가면서 사용되겠죠?
                    ENDWHILE
            ENDIF
ENDIF

위의 예시는 어디까지나 예제이고

                        item = item("DIAMOND_SWORD", 1) // 다이아 검 아이템 생성
                        #CALL "menu:updateitem" // 이 부분이 바로 네임드 트리거를 사용하는 부분.

이 부분 사이에 addLore()를 넣는식으로 서버에 대한 좀더 자세한 설명을 넣어도 될겁니다. 하이픽셀도 그렇게 되어있죠?

즉 자신이 원하는 바에 따라 무궁무진한 가능성이 있습니다.

댓글목록

등록된 댓글이 없습니다.

상단으로


모바일 버전으로 보기