개인 자료란 (JE)

  서버 커뮤니티

자료란에 모든 게시글은 반드시 자료란 글작성 가이드를 준수해야합니다. 글 작성 전에 반드시 확인해주세요!

한국 마인크래프트 포럼

마인크래프트 자료 및 커뮤니티 플랫폼

전체 회원수 122,990명 ( +30명 )

※ 장기간 미활동 회원 제외

Profile 브혼 개발자

Vhone dc73ee51d49946dabf4f634c6e3ce5c6

Profile

자료란new 공통new 리뷰, 강좌new 스크립트

[알고리즘] 애드온 없이 GUI 구현하기

2020.08.21 조회 수 1711 추천 수 0
자료글 링크 http://버킷 

여는 글

안녕하세요 브혼입니다. 간만에 코드 포스팅이네요.
GUI 구현에 대해서 이곳에서도 질문 주시고, 디코나 톡으로도 주시는 분들도 있어서 포스팅으로 남깁니다.

네이버 블로그 등에서 구버전에서 동작하는 코드를 긁어 오신 분들 중에
format %slot% with %item% ~ 형태의 코드가 있다면 TuSKe 애드온이 필요합니다.
해당 애드온은 마인크래프트 1.10버전에서 업데이트가 중단된 애드온으로 현 버전에선 사용할 수 없습니다.

GUI를 구현하기 위한 이벤트나 익스프레션은 Skellett 애드온(Skript 2.1 버전)에서 처음으로 지원하기 시작했고,
Skript 2.2 버전에서 공식적으로 추가되었습니다. 후에 공식 지원됨에 따라 Skellett애드온에서는 제거 되었고요.

마인크래프트 1.13 업데이트에서 인벤토리 API가 변경됨에 따라 name of %inventory% 이 값을 반환하지 않는 버그가 생겼습니다.
그동안 해결되지 못하고 있다가 이번 Skript 2.5-beta1 업데이트에서 해당 이슈가 해결되었습니다.
따라서 이번 포스팅의 코드는 Skript2.5-beta1버전부터 가능합니다.


구성 요소

알고리즘

  1. GUI에서 아이콘으로 사용할 아이템들을 생성합니다.
  2. GUI로 사용할 가상인벤토리를 만들고 아이템을 에 넣어줍니다.
  3. 특정 트리거(커스텀 명령어나 이벤트)를 통해 플레이어에게 GUI를 열어줍니다.
  4. On Inventory Click 이벤트에서 플레이어가 어떤 슬롯의 아이템을 클릭하는지 판단하여 기능을 수행합니다.


 예제 실습

GUI는 필요에 따라 다양하게 구성될 수 있습니다.

플레이어가 슬롯을 사용하지 않고, 매뉴처럼 클릭으로 특정 기능이 동작하게 하는것이라면
한 개의 GUI를 만들어 모든 플레이어가 같이 사용하는 것이 좋습니다. 슬롯이 변동될 여지가 없기때문이죠.

그러나 가상인벤토리나 정보창처럼 플레이어마다 다르게 변경될 필요가 있다면 플레이어마다 GUI를 생성해 줘야합니다.

전자의 경우 [On Load ] 이벤트에서 필요한 재료를 모두 구성하는 것이 좋고,
후자의 경우 GUI 생성 알고리즘을 펑션으로 만들어두거나, GUI 요청이 들어오는 부분에 작성해 두어야겠죠.

이번 예제는 전자의 케이스입니다.


on load:

    # [1] 필요한 아이템을 세팅합니다.
    set {gui::exemple::slot::3} to iron ingot named "&r1번 아이콘"
    set lore of {gui::exemple::slot::3} to "&r1번 첫번째 설명" and "&r1번 두번째 설명"
    
    set {gui::exemple::slot::4} to gold ingot named "&r2번 아이콘"
    set lore of {gui::exemple::slot::4} to "&r2번 첫번째 설명" and "&r2번 두번째 설명"
    
    set {gui::exemple::slot::5} to diamond named "&r3번 아이콘"
    set lore of {gui::exemple::slot::5} to "&r2번 첫번째 설명" and "&r2번 두번째 설명"
    
    # [2] 가상인벤토리를 생성합니다.
    suppress variable save warning
    set {gui::exemple::inventory} to chest inventory with 1 rows named "예제 GUI입니다"
    
    # [2-1] 가상인벤토리에 아이템을 배치합니다.
    loop {gui::exemple::slot::*}:
        set {_slot} to loop-index parsed as integer
        set slot {_slot} of {gui::exemple::inventory} to loop-value

[1]에서 리스트의 인덱스는 아이템이 배치될 슬롯 번호입니다.
[2-1]에서 GUI에 아이템을 배치할 때 쓰입니다.

[2]에서 인벤토리를 생성할 때 인벤토리는 변수에 담을 수 있지만, variables.csv 파일에 저장될 수 없습니다.
때문에 전역변수에 인벤토리를 담으면 '저장할 수 없어 데이터를 잃는다'는 경고메세지가 표시됩니다.
이 경고문구를 제거하려면 [suppress variable save warning]를 코드 위에 추가하면 됩니다.

[2-1]에서 리스트의 인덱스는 text타입이고 슬롯은 integer타입이 필요합니다.
[Parse]를 사용하여 integer타입으로 변환해줍니다.


command /gui.open:
    trigger:
    
        # [3] 미리 생성한 GUI를 열어줍니다.
        open {gui::exemple::inventory} to player

명령어로 플레이어가 GUI에 접근 할 수 있게 합니다.


on inventory click:

    # [4-1] GUI를 사용중이면 클릭이벤트를 취소하고 다음 코드로 넘어갑니다.
    current inventory of player is {gui::exemple::inventory}
    cancel event
    
    # [4-2] [On Load]이벤트에서 생성한 아이템으로 클릭한 아이템을 판단하여 기능을 수행합니다.
    set {_slot} to index of clicked slot
    set {_item} to clicked slot
    
    if {_item} is {gui::exemple::slot::3}:
        send "[분기 1번] %{_slot}%번 슬롯을 클릭했습니다.%nl%클릭한 아이템은 [%{_item}%]입니다."
    
    else if {_item} is {gui::exemple::slot::4}:
        send "[분기 2번] %{_slot}%번 슬롯을 클릭했습니다.%nl%클릭한 아이템은 [%{_item}%]입니다."
        
    else if {_item} is {gui::exemple::slot::5}:
        send "[분기 3번] %{_slot}%번 슬롯을 클릭했습니다.%nl%클릭한 아이템은 [%{_item}%]입니다."

예제에서는 [On Load ]이벤트에서 생성한 아이템과 클릭한 아이템을 비교했습니다.
이런 형태로 디자인을 하면 아이템의 위치에 상관없이 아이템을 클릭하면 기능이 동작하게 됩니다.

만약 [On Load ]이벤트에서 아이템이 아닌 슬롯 번호를 저장했다면 아이템에 상관없이 슬롯 클릭으로 동작하게 됐겠죠.


전자의 방법은 레이아웃이 자주 바뀔 수 있는 상황에 도움이 됩니다.
두더지 잡기게임 처럼 같은 요소가 여러슬롯에 나타 날 수 있는 환경에 유리하겠죠.

후자의 방법은 레이아웃은 바뀌지 않고 아이템이 자주 바뀌는 상황에 도움이 됩니다.
슬롯머신, 주식 트레이딩과 같이 아이템과 정보만 바뀌는 환경에 유리하겠죠.


send "~" 부분에 필요한 코드를 추가하면 됩니다.
다른 GUI를 열어야 한다면 [Open/Close Inventory]이펙트를
명령어를 실행할 것이라면 [Command]이펙트를 사용하면 됩니다.


on unload:
    delete {gui::*}

불필요한 전역변수가 남는게 껄끄러우시다면 [On Unload ] 이벤트에서 삭제하세요.

GUI 구현은 필요에따라 다양한 바리에이션이 있습니다.
먼저 예제를 따라 해보시고, 코드를 제대로 이해하고 응용해 보시기 바랍니다.



닫는 글

그동안 GUI 질문을 정말정말 많이 받았습니다.
대부분은 개발중단 되거나, 비주류인 애드온을 사용해서 코드를 맞게 작성했음에도 동작하지 않는다는 것이었는데요...

GUI는 애드온이 필요 없습니다!

GUI는 애드온이 필요 없어요!

[마크에서하는 야추(Yacht Dice)] 스크립트도 애드온 없이 구현된거라구요오옷!


11개의 댓글

IPECTER
2021.03.08

감사합니다!!! 개발자님!! 덕분에 애드온오류없이 스크립트로 GUI를 만들 수 있게되었어요!!! 정말 감사합니다!!

마린잉엥
2020.10.05

한마포 계속 회원가입이 안되서 난감했는데 이제 되었네요

 

on inventory click:

current inventory of player is {gui::exemple::inventory}

cancel event

 

set {_slot} to index of clicked slot

set {_item} to clicked slot

 

if {_item} is {gui::exemple::slot::10}:

execute console command "/say Hello everyone!"

execute op command "/say Hello everyone!"

execute player command "/say Hello everyone!"

 

 

send "[분기 1번] %{_slot}%번 슬롯을 클릭했습니다.%nl%클릭한 아이템은 [%{_item}%]입니다."

 

스크립트는 정상 업로드 되고 gui 창도 정상적으로 잘 열립니다.

근데 슬롯 10번 아이템을 누르면 아무 반응도 없고

아무것도 실행되지 않습니다..

 

10번 슬롯을 누르면 명령어가 실행되게 하고 싶습니다. 어찌해야 할까요?

브혼
2020.10.05
@마린잉엥

execute 이펙트의 조건문은 clicked slot과 비교됩니다. clicked slot은 클릭한 슬롯의 아이템을 가지고 있구요.

슬롯 번호를 비교하려면 index of clicked slot을 비교하세요.

마린잉엥
2020.10.05
@브혼

execute 이펙트도 조건문이 있군요 ㅠㅠ

어렵네요.

 

on inventory click:

clicked slot is {gui::exemple::slot::10}

cancel event

execute command "/say hello everyone" by player

 

이렇게 하면 될까요?

브혼
2020.10.05
@마린잉엥

코드를 읽을 수 있어야합니다. 그냥 복사, 붙여넣기로는 전혀 도움되지않아요.

당장 필요한 기능이면 코드를 짤 수 있는 분께 커미션을 드리던가,

공부를 하시려는 것이면 스크립트의 기본요소(이벤트, 컨디션, 이펙트, 익스프레션, 타입)에 대해서 알아보시고
그 다음 기본 문법(변수, 조건문 if, 분기if~else, 반복문 loop/while)에 대해 알아보시고
스크립트 설치시 기본적으로 설치되는 예제들을 읽고 해석 할 수 있는 단계까지는 스스로 준비를 하셔야합니다.
그리고 [스크립트 문서]를 보고 필요한 요소를 찾고 활용 할 수 있어야합니다.

읽을 줄 모르는데 사용하려고만 하는것은 욕심입니다.



clicked slot 은 슬롯 타입으로 아이템과 슬롯번호를 가지고 있습니다.
{gui::exemple::slot::10}은 아이템을 담은 변수이구요.
슬롯 타입과 아이템은 서로 다른 타입이므로 비교할 수 없습니다.

마린님이 구현하고자하는 기능은 10번 슬롯을 클릭했을때 어떠한 동작을 하는것입니다.
그렇다면 클릭한 슬롯의 번호가 필요하구요.
슬롯의 번호는 앞서 단 덧글에도 말씀드렸다시피 index of clickded slot입니다.
index of ~ 라는 익스프레션을 통해 슬롯타입으로부터 슬롯 번호를 꺼낼 수 있는것입니다.

그리고 이 슬롯번호가 10이 맞는지 컨디션을 통해 조건을 달아주면 됩니다.
index of clicked slot is 10
이렇게요.

마린잉엥
2020.10.05
@브혼

무슨 코드인지 영어와 관련있기에 해석은 다 되는데 스크립트 버전마다 다 다르게

답이 하나로 정해져있어서 그걸 배우는 게 참으로 어렵네요..

 

예를 들어, hello 랑 hi랑 같은 의미인데

스크립트마다 hello는 오류, hi는 정답 이렇게 되있어서 정말 까다로워요..

코드는 융통성으로 하는 게 아니라 오직 정답, 정확성이 중요한 분야라서 그런걸까요? 


그나저나 정말 대박이시네요...

index of clicked slot is 10: 이거 하나 붙였을 뿐인데

바로 작동 잘됩니다... 이런 건 

어떻게 아시는건지 대단하셔요

브혼
2020.10.05
@마린잉엥

스크립트는 그나마 다른 프로그래밍 언어에 비해 사람말에 가까운 언어입니다.

본래 프로그래밍 언어는 한가지 기능에 한가지 표현이 맵핑됩니다.

그래서 오해할 소지가 없는 명백한 표현이 가능한데요.

 

스크립트는 사람말에 가깝게 표현하기위해 패턴이라는 것을 차용했습니다.

예를들어

 

location of player와 player's location는 영문법적으로 같은 말입니다.

스크립트는 이 두 표현을 패턴으로 정의하여 두 표현이 같다고 이해를 합니다.

 

표면적으로는 좋아보이지만 이것은 프로그래밍을 하는데 아주 치명적인 단점입니다.

스크립트는 쉽게 배우고 간단하게 구현하기 위해서 패턴을 차용했지만

여러사람이 작업하는 대규모 프로젝트라면 절대로 이러면 안됩니다.

제가 만든 코드와 다른사람이 만든 코드가 같은 기능을 하지만 다르게 표현되어있다면 서로의 코드를 이해하는데 시간을 낭비하겠죠.

 

프로그래밍은 논리적인 구조체를 만드는 일입니다. 명확하고 정확한게 최우선이죠.

스크립트는 여러가지 패턴을 만들어 사람말에 가깝게 하고자 했지만, 결국 사용자가 사용하는 패턴은 한두가지로 귀결됩니다.

마린잉엥
2020.10.05
@브혼

한가지 기능에 한가지 표현이라는 말씀, 정말 큰 공감합니다..

그래서 프로그래밍 하시는 분들이 정말 대단하게 느껴집니다.

 

위 구문을 예시로만 들어도 참 재밌는 게 있습니다.

 

if {_item} is {gui::exemple::slot::10}:

execute console command "/say Hello everyone!"

 

이렇게 하면 스크립트 리로드할 때 success 화면 나오면서 정상적이라면서 재실행되는 데

실제 기능은 아무것도 작동하지 않습니다.

 

index of clicked slot is 10:

execute console command "/say Hello everyone!"

 

이렇게 하면 스크립트 리로드할 때 error 화면 뜨면서 비정상적이라는데

(Encountered errors while reloading the config and all scripts)

재밌는건 오히려 제가 원하는 모든 기능들이 정상적으로 작동이 됩니다.

 

프로그래밍은 오직 한가지 기능에 한가지 표현을 하되

프로그래밍은 작동이 되는 것도 작동이 안되는 것도

한가지 기능에 한가지 표현만 한다면 모두 정상적인 결과로 보는 거 같아요

 

여기에 왼쪽 마우스 버튼으로 10번 슬롯을 누를 경우라는

click type is left mouse button, click type을 정해주면 또 오류라면서 의사 소통이 안되는 게

프로그래밍을 배우기 어렵고 가장 큰 단점이 아닌가 싶습니다.

 

숫자 1 = 숫자 1 이러한 1차원적인 단일 기능, 단일 표현만이 컴퓨터가 이해를 하며

사탕이 1개있다. 고양이가 1마리있다. 이런 표현은 컴퓨터가 1이란 것을

전혀 인식을 못하는 거 같아서 답답함이 크네요.

 

한가지 기능에 한가지 표현으로만 한다면

상황만 주어지면 모든 프로그래밍 언어가 전부 작동을 안될 수 밖에 없어서

표현하는 데 있어서 상당히 비효율적이며 언어의 대부분이 낭비되기에

이를 조금은 보완하기 위해서 스크립트가 나온 게 아닌가 싶은데.. 스크립트도 많이 답답하네요

 

그래서 프로그래밍 하시는 분들을 보면 정말 존경스럽고 대단하다고 생각이 듭니다.

명이
2020.08.22

2.5 -beta2에서도 가능하겠져?

브혼
2020.08.22
@명이

명이
2020.08.22

와! 좋은 강좌군요!

컨텐츠
https://www.koreaminecraft.net/files/thumbnails/180/890/002/262x150.crop.jpg?20211025201038

시험지

한마탐 5주차 (한마포 마인크래프트 탐구 영역) (10 / 25) 3

베개냥이

2021-10-25

2

https://www.koreaminecraft.net/files/thumbnails/291/881/002/262x150.crop.jpg?20211021165153

데일리픽

초간단 전투기 만들기 8

megat88

2021-10-20

4

https://www.koreaminecraft.net/files/thumbnails/850/878/002/262x150.crop.jpg?20211018191640
(포션 시리즈) 3편 - 비 3

GlassesFilm

2021-10-18

4