CraftTweaker / MineTweaker
(크래프트트위커 / 마인트위커)

원 개발자 : StanHebben, Jaredlll08
마인크래프트 버전 : 1.7.10 ~ 1.12 (1.12 기반)

 

트위커 스크립트도 언어야 언어!

본격적으로 스크립트를 굴려먹기 전에 우리는 트위커 스크립트 내부가 어떻게 돌아가는지 알아야 할 필요가 있습니다. 우리가 트위커한테 스크립트 파일 안에 "이거 추가해!" 라고 써줘도 모드가 알아들을까요? 아닙니다. 모드는 우리가 개떡같이 말해줘도 찰떡같이 알아듣는 그런 똑똑한 놈이 아니죠. 그러기에 우리는 모드가 알아들을 수 있는 언어로 말해줄 필요가 있습니다.

트위커는 기본적으로 ZenScript라는 언어로 돌아갑니다. 이름부터 JS 베낀게 팍팍 티나듯이 문법도 자바스크립트랑 비스무레하죠. 근데 실상 돌아가는 구조는 살짝 다릅니다! 클래스도 없고 타입이 거의 없다시피한 자바스크립트와는 다르게 클래스나 타입이 철두철미한 C++이나 자바같은 특성이 암암리에 섞여있는... 한마디로 짬뽕언어죠. 이런 미묘한 특징때문에 잘 숙지하지 않은 채로 트위커로 고급 기능을 구현 시도하면 에러 폭발하고 피토하는게 한두 차례가 아닐 겁니다. 구에엑

아무튼.. 이번 강좌에서는 간단한 몇가지 문법 요소를 소개해보려합니다. 어차피 기본적인 문법들은 뭔 언어든 비슷비슷하지 않겠어요? ㅋㅎㅎ

 

 

0. 시작하기 전에

 젠스크립트는 종결자로 ;(세미콜론)을 갖고 있습니다. 즉 코드가 끝나면 항상 세미콜론을 붙여줘야 한다는 것이죠! 잊지 말아 줍시다.

 

 

1. 변수와 상수

 변수와 상수! 기초 중의 기초이자 필수적인 요소입니다. 바로 앞으로 써먹을 값들을 좀 더 편리하게 굴려먹기 위해 데이터들을 지시해주는 것이죠.

 트위커에선 이들의 관리가 여러분 스크립트의 질을 좌우하는 중요한 요소로 작용합니다. 관리를 깔끔하게 한 스크립트는 가독성도 좋고 유지보수도 쉽지만, 그렇지 못한 건 바로 휴지통에 넣고 싶어질 정도로 상태가 암담해지죠 (초어둠

 그만큼 변수와 상수의 관리는 아주아주 중요하니, 이 글을 읽고 계신 여러분께선 이게 중요하단 걸 최대한 빨리 깨달아야 합니다 흑흑..

 

 일단 변수를 선언하려면 자신이 변수를 어떤 용도로 쓸 것인가에 따라 키워드를 입력해줘야 합니다. 젠스크립트에선 변수를 선언해줄 수 있는 키워드가 1.12 이전까지는 var val, 이 두 가지밖에 없었는데 1.12부터는 새롭게 global static 키워드가 추가됩니다. 하나씩 알아가보도록 합시다.


 1.1. var 

 var foo;
 var seren = "geungji";
 var iron = <minecraft:iron_ingot>;

 // seren이란 변수가 이미 선언되었으므로, var를 생략할 수 있다.
 seren = "thangorodrim"; 
 iron = 1;

 

 아마도 가장 많이 쓰게 될 키워드 var 입니다. variable에서 따옴에서 짐작할 수 있듯이 이 키워드는 변수를 의미합니다. , 값 변경, 중복 적용이 가능합니다.

위의 스크립트를 예로 들자면, seren이란 변수를 처음에 "긍지"라는 문자열로 선언했는데, 뒤에는 "상고로드림"이라는 문자열로 값을 변경한 것을 볼 수 있습니다. iron이란 변수를 처음엔 마인크래프트 철 주괴 아이템으로 선언했다가, 뒤에는 1이라는 숫자로 다시 적용된 것을 볼 수 있습니다.

 

 이러한 특성을 지닌 var은 스크립트 상에서 주로 일반적인 값을 선언할 때나 값 변경이 잦은 값들을 사용할 때 많이 활용됩니다.

 

 1.2. val  

  val foo; 
# foo = <minecraft:apple>; // 변경 불가능하다.

  그 다음으로 소개드릴 키워드는 val 입니다. 이 변수는 한 번 정의가 되면 그 값을 변경할 수도, 중복 적용도 할 수 없습니다.

그렇습니다! 상수가 된다는 것입니다! 보통 스크립트 상에서 고정시켜두고 써먹을 상수(예를 들어, 오어 딕셔너리)를 정의할 때 많이 쓰입니다.

 

 1.3. global과 static

 1.12부터 추가된 새로운 개념의 변수들입니다. 바로 전역변수. 이 변수를 활용하기 위해선 먼저 Scope(범위)의 개념을 알아야하기 때문에, 고급 트위커 문법에서 다뤄질 예정입니다.

 

 

2. 타입

 타입은 변수에 실질적으로 지시될 값의 종류를 나타냅니다! 젠스크립트 문법의 모체가 되는 자바스크립트는 타입의 종류가 거의 없다시피 해서, var를 쓸 때도 타입의 경계가 굉장히 모호하다는 것이 특징입니다. 그런데 우리가 다룰 젠스크립트는 JS와는 다르게 이러한 타입의 구분이 착착 되어있습니다! 타입 구분이 자바랑 아주 흡사하죠. 아무래도 마인크래프트의 NBT같은 데이터를 다뤄야하고, 무엇보다 자바 위에서 구성된 인터프리터 언어라서 그런 걸까요?

 
이게 아주 큰 차이점이기에 실제로 스크립트 상에서 변수를 다룰 때 타입의 명시 여부가 여러분의 스크립트가 잘 굴러가는가! 아니면 에러의 나락으로 빠져버리는가.. 가 결정되기 때문에 중요하게 눈여겨 볼 필요가 있습니다.

 

 2.1. 타입의 종류 

 아무래도 우리가 변수나 상수를 선언하기 전에, 우리는 쓸 값의 타입을 먼저 결정해야겠죠? 우리가 쓸 수 있는 타입의 종류는 무엇이 있는지 봅시다.

대표적으로 많이 쓰이는 타입들의 종류는 아래와 같습니다. 자바랑 비슷해요!

 

 

 

 

옆의 IData 계열이나 IIngredient 계열같이 분류한 이유는 이 젠스크립트의 타입들이 어떤 식으로 쌓아 올려졌나를 보면 알 수 있습니다.
젠스크립트는 자바 위에서 돌아가서 젠스크립트의 타입마다 대응하는 클래스가 있습니다! bool 타입은 DataBool에 대응하는 식으로요. 이러한 클래스들은 전부 IData IIngredient란 클래스를 상속하는 구조입니다. 쉽게 예를 들어 말하자면 보낌이나 양명같은 분들이 타입이고, 유튜브 크-리에이터나 우가우가 BJ IData IIngredient같은 거라 보면 얼추 비슷합니다. 후후..

 이에 대한 자세한 구조 설명은 고급 트위커 문법에서 ZenClass와 함께 다룰 예정입니다.

 

 2.2. 타입의 선언

  타입의 종류를 살펴봤으니, 본격적으로 타입을 선언하는 방법에 대해서 알아봅시다!

 var foo; 
 foo = <minecraft:iron_nugget>;

 위의 코드에서 변수 foo의 타입은 무엇일까요? 철조각이란 IItemStack을 지시해주는 걸까요? 실제로 foo란 변수로 레시피 제거나 변경을 시도하면 에러 메시지를 구에엑 토해낼 겁니다.

이유는 타입은 변수가 선언될 시점에 결정되기 때문입니다. 즉, 위의 foo IItemStack도 아니고, IIngredient도 아닌 그냥 IAny라는, 타입이 결정되지 않은 상태가 되어버리는 겁니다. 한마디로 못 써먹는다는 소리죠.

 

 그럼 어떻게 해야하느냐! 아래 코드를 봅시다.

// IIngredient 계열 타입들은 import로 해당하는 타입의 클래스를 불러줘야한다.
import crafttweaker.item.IItemStack;

  var foo = <minecraft:iron_ingot>;

  var apple as IItemStack = <minecraft:apple>;
# apple = 1; // apple 변수엔 IItemStack만 올 수 있다.
  apple = foo;

 위에서 설명했듯이, 타입은 변수가 선언될 시점에 결정된다고 했었죠? foo 변수는 선언될 때 <minecraft:iron_nugget>이란 값으로 선언하였으므로, 타입은 IItemStack으로 결정됩니다.

 

그렇다면 특정한 값으로 선언하지 않고, 변수 자체의 타입을 결정할 방법은 없는걸까요? 아닙니다. 바로 as라는 타입을 결정해주는 키워드를 사용하면 됩니다.
 위와 같이 변수명 옆에 as <type>를 붙이시면 apple이란 이름의 변수는 IItemStack으로 타입이 고정되는 것이죠. 게다가 IItemStack 이외의 타입은 올 수 없는 타입 세이프 기능까지 쓸 수 있다는 것도 확인할 수 있습니다. 이런 식으로 변수에 타입을 매겨서 활용하면, 나중에 함수 같은 기능을 사용할 때 굉장히 유용합니다.

 

 2.1. 타입 형변환(캐스팅) 

 만약 어떤 값이 있다면 이 값의 타입을 다른 타입으로 변경할 수는 없을까요? 있습니다! 마찬가지로 as 키워드를 사용하시면 타입 변환이 가능합니다.

 var foo = 15;
 var foo_str = foo as string;

 print(foo_str);

  foo는 15라는 값을 갖고있는 정수형의 int입니다. 하지만 foo_str란 변수는 foo를 string으로 형변환하였으니 “15”라는 문자열 형태의 값을 갖게 됩니다. 따라서 print(foo_str)는 15를 출력하게 됩니다.

다만 상호 변환이 되는 것이 있고 안 되는 것도 있습니다. 예를 들면 0.5라는 실수형 타입의 값을 다른 실수형으로 바꿀 수 있지만, 배열이나 Map을 정수형으로 바꿀 수 없죠. 아래는 그걸 정리한 표입니다.

 

 

 

 

( 출처 : https://crafttweaker.readthedocs.io/en/latest/#Vanilla/Data/IData/#overview )


float, double같은 실수형 같은 타입이 int같은 정수형으로 형변한이 된다는 것이 조금 의아하신 분들도 계실 겁니다. 0.5 3.14같은 게 정수형으로 형변환된다고? 됩니다! 물론 소수점 자릿수가 전부 상실된 채로 형변환될 뿐이죠.

 

 젠스크립트 상의 형변환은 자바의 형변환을 따르게 되어있습니다. 실수형이 정수형으로 형변환될 때도 소수점을 잃는다던가, long이나 int같은 바이트 수가 큰 타입이 byte short같은 작은 타입으로 다운캐스팅되는 것도 자바랑 동일하게 이뤄집니다.

 

+ Recent posts