강의 환경 : forge-1.7.10-10.13.4.1517-1.7.10

 

배경 지식

  1. 기본 아이템
  2. 아이템 스택

 

강의목표

  1. 아이템의 메타데이터(metadata)를 이해한다.
  2. 아이템의 손상 값(Damage)을 이해한다.
  3. 손상 값(Damage)을 이용해서 하위 아이템을 만들 수 있다.

 

1. 아이템의 메타데이터

메타데이터(Metadata)는 데이터를 설명하기 위한 추가적인 데이터입니다. 예를 들면, 디지털 카메라에서는 사진을 찍을 때마다 촬영 시간, 노출, 플래시 사용 여부, 해상도, 사진 크기 등의 정보를 화상 데이터와 같이 저장하게 되어 있습니다. 이런 추가적인 데이터는 훗날 사진을 정렬하고 관리할 때 상당히 유용한 지표가 됩니다. 메타데이터는 일반적으로 이처럼 데이터의 검색과 관리를 편리하게 하기 위해서 부여됩니다.

마인크래프트에서 말하는 메타데이터는 약간 차이가 있습니다. 마인크래프트 세계에는 최소 수 백만 개의 블록이 존재하기 때문에 각 블록에 저장될 수 있는 데이터가 많지 않습니다. 일단 서로 다른 블록을 구분하도록 ID값이 저장되고, 거기에 추가적으로 4비트만큼의 저장 공간이 제공됩니다. 0~15까지 저장할 수 있는 이 공간을 메타데이터라고 부릅니다.

이러한 메타데이터는 단순한 데이터를 저장할 때 사용됩니다. 양털의 색, 화로의 방향, 도가니의 물과 같이 몇 개의 숫자만으로 충분히 표현 가능한 자료들을 저장합니다. 양털은 파괴되어 아이템이 된 후에도 그 색이 보존되기 때문에 아이템 스택에도 메타데이터를 저장하는 공간이 있다는 것을 유추할 수 있습니다. 이 값이 바로 아이템의 메타데이터입니다.

그림 1서로 다른 양털

 

 

2. 손상 값(Damage)

앞서 말한 메타데이터는 damage라는 변수에 저장됩니다. 이름 그대로 도구 아이템의 내구도를 나타낼 때 흔히 사용됩니다. 그렇기 때문에 내구도가 있는 도구는 메타데이터까지 따로 저장할 수는 없습니다. 한 변수에 두가지 정보를 저장하는 것은 굉장히 번거로운 일이니까요. 블록과 달리 아이템의 메타데이터는 -32768~32767의 훨씬 넓은 저장공간을 제공합니다.

이번 강의에서는 손상 값을 이용해서 하위 아이템을 만드는 법을 알아볼 것입니다. 이러한 방식이 가진 장점은 1) 32000까지 제한되어 있는 아이템 ID를 절약할 수 있고 2) 메타데이터를 이용하는 블록과 연계된 아이템을 만들 수 있으며, 3) 마지막으로 손상 값 자체를 응용해서 유연한 프로그래밍을 할 수 있습니다.

 

 

3. 하위 아이템을 사용하는 Item 클래스

지난 강의에서 추가한 기본 아이템과는 다르게 특수한 기능을 가지고 있기 때문에 새로 클래스를 작성해야 합니다. 객체지향의 원리에 따라 Item 클래스를 상속해야만 호환이 됩니다. 우선은 다음과 같이 클래스를 작성합니다. 패키지는 지난 강의와 같은 oortcloud.basictutorial.item으로 하겠습니다.

ItemMetadata.java

package oortcloud.basictutorial.item;

 

import net.minecraft.item.Item;

 

public class ItemMetadata extends Item {

 

}

여기서 하위 아이템을 가지는 아이템은 반드시 setHasSubtypes 메소드를 이용해서 해당 아이템이 하위 아이템을 가지는 것을 명시해야 합니다. 그렇지 않으면 서로 다른 손상 값이 모두 무시되어 인벤토리에서 그냥 겹쳐집니다. 이 사항은 하위 아이템을 가지는 모든 아이템 객체에 대해서 해당되는 사항이므로 생성자에 포함시키도록 하겠습니다.

ItemMetadata.java

public ItemMetadata() {

    setHasSubtypes(true);

}

그럼 이대로 적절한 이름(Unlocalized Name)을 부여해서 등록해보도록 하겠습니다.

ModItems.java

public final class ModItems {

    

    public static Item itemNumber;

    

    public static final void init() {

        itemNumber = new ItemMetadata().setUnlocalizedName("itemNumber").setCreativeTab(CreativeTabs.tabMisc);

        GameRegistry.registerItem(itemNumber, "itemNumber");

    }

    

}

/give 명령어를 이용해서 서로 다른 손상 값을 가지는 아이템을 받아보면 서로 겹쳐지지 않는 것을 확인할 수 있습니다. 반대로 조약돌은 아무리 손상 값을 달리해도 그냥 한 종류의 아이템으로 취급됩니다.

그림 2하위 아이템

여기서 우리는 총 세가지 문제를 확인할 수 있습니다. 1) 이름이 올바로 표시되지 않는다. 2) 텍스처가 올바로 표시되지 않는다. 3) 크리에이티브 탭에 한 종류(손상 값이 0)만 나타난다. 하나씩 해결해보도록 합시다.

 

1) 손상 값에 따른 이름(Unlocalized Name) 지정

아바스토로님의 강의를 참고하면 언어 설정에 맞게 올바른 이름이 표시되게 할 수 있습니다. 하지만 이 방법만으로는 setUnlocalizedName을 통해 부여한 이름이 단 하나의 번역에 대응되기 때문에 손상 값에 따라 다른 이름을 부여할 수는 없습니다. 따라서 손상 값에 따라 현지화 되지 않은 이름(Unlocalized Name)이 바뀌도록 해야합니다. lang파일이 다음처럼 서로 다른 손상 값에 대해 대응될 수 있도록 말이죠.

en_US.lang

item.itemNumber_0.name=Number Zero

item.itemNumber_1.name=Number One

item.itemNumber_2.name=Number Two

item.itemNumber_3.name=Number Three 

 

우리가 작성한 ItemMetadata 클래스 안에서 getUnlocalizedName(ItemStack itemStack)이라는 메소드를 오버라이드하면 아이템 스택의 손상 값이나 NBT 값에 따라서 서로 다른 이름을 대응시킬 수 있습니다. 우리는 손상 값에 따라 이름을 달리 지정할 것이므로 간단히 본래의 이름 뒤에 _(손상값)을 붙이도록 합시다.

ItemMetadata.java

@Override

public String getUnlocalizedName(ItemStack itemStack) {

    return getUnlocalizedName()+"_"+itemStack.getItemDamage();

}

getUnlocalizedName()은 아이템 스택의 상태(손상 값, NBT)에 영향 받지 않는 setUnlocalizedName()으로 등록한 이름 그 자체를 반환하고, itemStack.getItemDamage() itemStack 의 손상 값을 반환합니다.

 

다시 실행해보면 이름 문제는 해결된 것을 확인할 수 있습니다.

 

2) 손상 값에 따른 텍스처 지정

텍스처를 지정하는 과정은 2단계로 이루어집니다. 먼저 다수(혹은 하나)의 텍스처를 등록을 하고, 아이템 스택의 정보를 받아 상황에 맞는 텍스처를 반환하는 형식입니다. 우리는 사용할 텍스처를 모두 등록해서 배열에 저장한 후 주어진 아이템 스택의 손상 값에 맞는 텍스처를 반환하도록 하겠습니다.

텍스처 등록은 해당 아이템의 클래스 내에서 registerIcons(IIconRegister iconRegister) 메소드를 오버라이드하여 제어할 수 있습니다. 앞서 말했듯이 이렇게 등록한 텍스처(IIcon) 객체를 저장해 두어야하기 때문에 해당하는 배열 또한 클래스의 멤버 변수로서 생성해두도록 하겠습니다. 본 강의의 경우에는 ItemMetadata 클래스 내부에 다음의 코드를 추가로 작성하게 됩니다.

ItemMetadata.java

public IIcon[] icons = new IIcon[4];

 

( … )

 

@Override

public void registerIcons(IIconRegister iconRegister) {

for (int i = 0; i < icons.length; i++) {

this.icons[i] = iconRegister.registerIcon("basictutorial:itemNumber_" + i);

}

}

iconRegister.registerIcon 에 전달되는 인자는 setTectureName 메소드와 형식이 동일하여 (Mod ID):(파일 이름)의 형태로 작성해주시면 됩니다.

이제 getIconFromDamage(int damage) 메소드를 오버라이드해서 아이템의 손상 값에 따라 서로 다른 텍스처(IIcon)를 전달할 수 있습니다. /give 명령어를 사용하면 우리가 고려하지 않은 손상 값을 가진 아이템 스택도 생성될 수 있으므로, 사전에 꼭 손상 값을 확인하도록 합시다. 이 또한 당연히 ItemMedata 클래스 내부에서 작성됩니다.

ItemMetadata.java

@Override

public IIcon getIconFromDamage(int damage) {

    if (damage > icons.length) {

        damage = 0;

    }

    return icons[damage];

}

 

텍스처 등록 및 지정과 관련된 모든 과정을 구현했습니다. 이제 텍스처 파일이 있어야 하는데, 4개의 파일을 제공해 드리겠습니다. 각 파일의 경로는 이전 강의와 당연히 동일하고, 파일 이름은 텍스처를 등록하는 과정에서 지정한 것과 동일합니다.

그림 3텍스처 등록

 

3) 크리에이티브탭에 등록

이 과정은 구현에 필수는 아니지만 사용자의 편의를 위해 구현 해두면 좋습니다. 마인크래프트에 등록된 아이템은 기본적으로 손상 값이 0인 아이템 하나만 크리에이티브 탭에 표시됩니다. 크리에이티브 탭에 표시될 아이템 스택들을 제어하려면 getSubItems(Item item, CreativeTabs tab, List list) 구현해야 합니다.

ItemMetadata.java

@Override

public void getSubItems(Item item, CreativeTabs tab, List list) {

    for (int i = 0; i < icons.length; i ++) {

list.add(new ItemStack(item, 1, i));

}

}

Item은 현재 등록하려는 item의 객체, tab은 현재 추가하려는 크리에이티브 탭의 종류, list는 지금까지 추가된 아이템들을 모두 보관하고 있는 리스트입니다. add명령어를 이용해서 우리가 원하는 아이템 스택을 등록해주면 됩니다.

그림 4크리에이티브 탭

 

최종적으로 작성된 코드를 보여드리겠습니다.

ItemMetadata.java

package oortcloud.basictutorial.item;

 

import java.util.List;

 

import net.minecraft.client.renderer.texture.IIconRegister;

import net.minecraft.creativetab.CreativeTabs;

import net.minecraft.item.Item;

import net.minecraft.item.ItemStack;

import net.minecraft.util.IIcon;

 

public class ItemMetadata extends Item {

    

    public IIcon[] icons = new IIcon[4];

    

    public ItemMetadata() {

        setHasSubtypes(true);

    }

    

    @Override

    public void getSubItems(Item item, CreativeTabs tab, List list) {

        for (int i = 0; i < icons.length; i ++) {

     list.add(new ItemStack(item, 1, i));

     }

    }

    

    @Override

    public void registerIcons(IIconRegister iconRegister) {

     for (int i = 0; i < icons.length; i++) {

     this.icons[i] = iconRegister.registerIcon("basictutorial:itemNumber_" + i);

     }

    }

    

    @Override

    public IIcon getIconFromDamage(int damage) {

        if (damage > icons.length) {

            damage = 0;

        }

        return icons[damage];

    }

    

    @Override

    public String getUnlocalizedName(ItemStack itemStack) {

        return getUnlocalizedName()+"_"+itemStack.getItemDamage();

    }

      

    

}

 

ModItems.java

package oortcloud.basictutorial.item;

 

import cpw.mods.fml.common.registry.GameRegistry;

import net.minecraft.creativetab.CreativeTabs;

import net.minecraft.item.Item;

 

public final class ModItems {

    

    public static Item itemNumber;

    

    public static final void init() {

        itemNumber = new ItemMetadata().setUnlocalizedName("itemNumber").setCreativeTab(CreativeTabs.tabMisc);

        GameRegistry.registerItem(itemNumber, "itemNumber");

    }

    

}

 

 

 

참고자료

http://bedrockminer.jimdo.com/modding-tutorials/basic-modding-1-7/metadata-blocks-and-items/

https://ko.wikipedia.org/wiki/%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0

http://minecraft-ko.gamepedia.com/%EB%8D%B0%EC%9D%B4%ED%84%B0_%EA%B0%92

강의 환경 : forge-1.7.10-10.13.4.1517-1.7.10

 

배경 지식

  1. 기본 모드 파일

 

강의목표

  1. 아이템 객체를 생성한다.
  2. 생성된 객체를 등록한다.
  3. 등록된 아이템에 텍스처(Texture)를 부여한다.

 

1. ModItems 클래스 만들기

아이템을 만들기에 앞서, 먼저 우리가 추가할 아이템들을 관리할 수 있는 클래스를 준비해야 합니다. 클래스의 이름이나 패키지는 기능과는 크게 관련 없지만 훗날 능률을 높이기 위해서 정해진 약속대로 정의하는 것이 좋습니다. 본 강의에서는 이름은 ModItems, 패키지는 oortcloud.basictutorial.item으로 설정하겠습니다.

그림 1패키지 탐색기

이제 ModItems 클래스의 뼈대를 구성해보도록 하겠습니다. 먼저, ModItems 클래스가 다른 클래스로부터 상속되지 않도록 final로 선언을 합니다. 그리고 아이템 객체를 생성하고 등록할 init() 메소드를 만듭니다. 이때 init() 메소드는 1) 외부에서 메소드를 실행할 수 있도록 public으로, 2) ModItems는 객체가 생성되지 않으므로 static으로, 3) 클래스와 마찬가지로 오버라이드 될 수 없도록 final로 선언해줍니다.

ModItems.java

package oortcloud.basictutorial.item;

 

public final class ModItems {

    

    public static final void init() {

        

    }

    

}

 

 

2. 아이템 객체 생성 및 성질 부여

뼈대가 완성되었기 때문에 간단히 Item 객체를 만들어 보도록 하겠습니다. 위에서와 같이 public static으로 선언해줍니다. 처음 아이템 변수를 선언할 때는 임포트와 관련된 에러가 발생할 수 있습니다. Ctrl + Shift + O를 누르면 이클립스에서 필요한 클래스를 자동으로 임포트 해줍니다.

ModItems.java

package oortcloud.basictutorial.item;

 

import net.minecraft.item.Item;

 

public final class ModItems {

    

    public static Item tutItem;

    

    public static final void init() {

        

    }

    

}

 

이제 tutItem 에 적용될 아이템 객체를 만들겠습니다. Item 객체는 하나 또는 여럿의 아이템 종류를 대표하여 생성되는 아이템 스택(Item Stack)의 이름, 텍스쳐, 성질을 결정합니다. 오늘 우리가 다룰 아이템은 단순히 Item 클래스의 생성자를 사용하면 됩니다.

ModItems.java

package oortcloud.basictutorial.item;

 

import net.minecraft.item.Item;

 

public final class ModItems {

    

    public static Item tutItem;

    

    public static final void init() {

        tutItem = new Item();

    }

    

}

 

이렇게 만든 객체는 당연히 아무런 기능이나 성질을 가지고 있지 않습니다. 심지어 이름조차 없기 때문에 등록할 수도 없습니다. 성질을 부여할 때는 다음과 같은 메소드를 사용합니다. 이들은 모두 조작한 객체를 다시 반환합니다. (이 부분은 예시를 보면서 추가로 설명하겠습니다)

setUnlocalizedName(String name)

아이템의 이름을 name으로 설정합니다.

setCreativeTab(CreativeTabs tab)

크리에이티브 모드의 tab에서 이 아이템을 찾을 수 있습니다.

setTextureName(String name)

텍스쳐의 이름을 name으로 설정합니다.

setMaxStackSize(int size)

중첩될 수 있는 최대 개수를 size로 설정합니다.

 

각 메소드가 다시 아이템 객체를 반환하기 때문에 예시와 같이 한 줄에 나열해서 호출할 수 있습니다. 아래의 아이템은 tutItem이라는 이름을 가지게 되고 크리에이티브 모드에서 기타 항목에 들어가게 됩니다.

tutItem = new item().setUnlocalizedName("tutItem").setCreativeTab(CreativeTabs.tabMisc);

 

 

3. 아이템 등록

이렇게 객체를 생성하더라도 마인크래프트 내부에 이식된 것이 아니라서 실제로는 게임에 아무런 영향도 주지 않습니다. 따라서 등록(registration)이라는 과정을 통해 아이템을 내부에 이식해야 합니다.

public static void GameRegistry.registerItem(Item item, String name)

Item item

등록할 아이템 객체입니다.

String name

setUnlocalizedName()에서 사용한 이름과 같은 이름입니다.

 

ModItems.java

package oortcloud.basictutorial.item;

 

public final class ModItems {

    

    public static Item tutItem;

    

    public static final void init() {

        tutItem = new Item().setUnlocalizedName("tutItem").setCreativeTab(CreativeTabs.tabMisc);

        GameRegistry.registerItem(tutItem, "tutItem");

    }

    

}

 

마지막으로 init()을 호출하기만 하면 등록이 완료 됩니다. 아이템의 등록은 다른 모드와 호환을 위해 최대한 빨리 진행해야 하기 때문에 Pre-Initialization 단계가 적합합니다. 다음과 같이 기본 모드 파일의 해당 이벤트에서 호출하면 됩니다.

BasicTutorial.java

( … )

    @Mod.EventHandler

    public static void preInit(FMLPreInitializationEvent event) {

        ModItems.init();

    }

( … )

 

그림 2추가된 아이템(1)

아이템이 추가되어 크리에이티브 탭에서 찾아볼 수 있습니다. 하지만 이름은 item.tutItem.name이고 텍스쳐는 검정/분홍 체스판입니다. 등록은 완료되었으나 아직 (현지화 된)이름과 텍스쳐가 올바로 지정되지 않았기 때문입니다. 이 중 텍스쳐는 곧 바로 추가할 것이고 현지화는 아바스트로님의 강의를 확인하시면 됩니다.

 

 

4. 텍스처 등록

먼저 등록할 텍스처를 준비해 보겠습니다. 크기는 기본적으로 16*16에 png 형식입니다. 아래의 텍스처는 제 모드인 토지 중개사(Estate Agent)에 사용된 파일입니다.

일단 이 텍스쳐를 "(WorkspaceRoot)/src/main/resources/assets/(modid)/textures/items/(texture_name).png"에 저장해야 합니다. 괄호로 표시된 값은 변수라고 생각하시면 됩니다. 본 강의에서 다루는 예제라면 다음의 경로에 저장해야 합니다.

그림 3텍스처 경로

 

이제 아이템 객체와 텍스처 파일을 연결해야 합니다. ModItems 클래스에 선언된 객체에 .setTextureName("(modid):(file_name)") 메소드를 호출합니다. 이 역시 괄호로 표시된 부분은 변수입니다. ":" 기호로 구분되어 앞은 모드 ID, 뒤는 연결할 PNG 파일 이름입니다.

.setTextureName("basictutorial:tutItem")

본 강의에서는 위와 같이 호출해야 합니다.

 

ModItems.java

package oortcloud.basictutorial.item;

 

public final class ModItems {

    

    public static Item tutItem;

    

    public static final void init() {

        tutItem = new Item().setUnlocalizedName("tutItem").setCreativeTab(CreativeTabs.tabMisc).setTextureName("basictutorial:tutItem");

        GameRegistry.registerItem(tutItem, "tutItem");

    }

    

}

 

 

 

참고 자료

http://bedrockminer.jimdo.com/modding-tutorials/basic-modding-1-7/first-item/

강의 환경 : forge-1.7.10-10.13.4.1517-1.7.10

 

배경 지식

  1. 무형 조합법(Shapeless Recipe) 및 화로 조합법(Smelting Recipe) 추가하기
  2. 유형 조합법(Shaped Recipe) 추가하기
  3. 광물 사전

 

강의목표

  1. 광물 사전을 이용한 조합법을 추가한다.
  2. 아이템의 내구도(damage)에 영향을 받지 않는 조합법을 추가한다.

 

1. 광물 사전을 이용한 조합법

마인크래프트 포지에는 광물 사전이라는 개념이 있어서, 비슷하거나 완전히 동일한 아이템을 하나의 이름으로 묶습니다. 원목의 경우에는 참나무, 가문비나무 등 여러 종류가 있지만 모두 "logWood"라는 이름으로 대표되고, 구리 주괴도 IC2에서, 포레스트리(Forestry)에서 각각 아이템을 추가하지만 "ingotCopper"라는 이름으로 연결되어 있습니다. 자주 사용되는 목록여기에서 찾아보실 수 있습니다. 다만 최신 버전은 아닙니다.

조합법을 추가할 때, 광물 사전을 이용하지 않으면 원치 않은 결과가 발생할 수 있습니다. 나무를 이용한 조합법이 등록할 때 사용한 한 종류의 나무만 지원하고, 광물을 사용하는 조합법이 다른 모드의 광물은 인식하지 않는다면, 사용자 입자에서 굉장히 불편할 것입니다. 광물 사전은 이와 같이 조합법을 추가할 때, 사실상 반드시 이용해야하는 기능입니다.

광물 사전 조합법은 IRecipe를 구현하고 있으며 유형 조합법, 무형 조합법이 각각 따로 작성되어 있습니다. 다만, 유형 조합법/무형 조합법과 같이 GameRegistry에서 따로 추가하는 함수가 정의되어 있지 않아 addRecipe라는 일반적인 등록 함수에 IRecipe 객체를 전달하는 방식으로 조합법을 추가하게 됩니다.

void GameRegistry.addRecipe(IRecipe recipe)

IRecipe recipe

등록될 조합법

 

광물 사전 조합법은 IRecipe를 상속하고 있기 때문에 위 함수의 인자로서 적합합니다. 즉, 우리가 원하는 조합에 대한 광물 사전 조합법의 객체를 만든 뒤 인자로 전달하기만 하면 등록이 끝나는 것입니다.

new ShapedOreRecipe(ItemStack result, Object... recipe)

ItemStack result

조합법 결과

Object... recipe

조합법 배치 및 재료들

 

new ShapelessOreRecipe(ItemStack result, Object... recipe)

ItemStack result

조합법 결과

Object... recipe

조합법 재료들

 

위 두 생성자는 지난 강의에서 살펴본 GameRegistry.addShapelessRecipe/GameRegistry.addShapedRecipe와 거의 같습니다. 다만 아이템 스택(Item Stack)뿐만 아니라 광물 사전 이름도 주어 줄 수 있습니다. 서로 거의 적용 방법이 비슷하니 유형 조합법만 예시를 살펴보겠습니다.

GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(Blocks.chest,8), "aaa","a a","aaa", 'a', "logWood"));

 



그림 1추가된 광물 사전 조합

위의 코드가 아래와 같은 조합법을 추가합니다. 상자 1개를 만드는 조합은 기본 조합이고, 포지(Forge)에서 자체적으로 광물 사전 조합으로 변경한 것을 알 수 있습니다. 아래가 추가된 조합법입니다. NEI를 사용해 보신 분들은 아시겠지만 광물 사전 조합법은 해당 광물 사전의 모든 아이템들이 무작위로 표시되며 바뀝니다.

 

 

2. 내구도에 영향을 받지 않는 조합법

아이템 스택(Item Stack)을 생성할 때, 인자로 내구도(damage) 값을 줄 수 있는 것은 이미 알고 계실 겁니다. 내구도 값에 따라 서로 다른 염료가 결정되고, 실제 도구의 손상 정도를 나타내기도 합니다. 조합법을 등록할 때도 적절한 내구도 값을 전달해서 명확한 조합법이 만들어 질 수 있습니다. 하지만 무기나 곡괭이를 이용한 조합의 경우에는 내구도 값이 조합법에서 문제가 되는 경우도 있습니다.

그림 2발사기 조합법(1)

한 번도 사용하지 않은 활이라면 위의 조합은 발사기(Dispenser)를 만들어야 합니다. 하지만 한 번 이상 사용한 활은 내구도 값이 다르기 때문에 조합법에서 다른 재료로 인식됩니다. 하지만 여기서 활의 가능한 모든 내구도(0, 1, 2, …)에 대해서 조합법을 추가하는 것은 성능을 저하시키는 요인이 됩니다. 결코 올바른 방법이 아니죠.

이런 상황에서는 아이템 스택(Item Stack)의 생성자에 일반적인 상수를 내구도 값으로 전달하는 것이 아닌 OreDictionary.WILDCARD_VALUE (=32767)라는 특수한 값을 전달하면 모든 내구도에 대해서 조합법이 재료를 인식합니다.

방법은 간단하기 때문에 바로 예시를 보며 강의를 마치겠습니다.

GameRegistry.addShapedRecipe(new ItemStack(Blocks.dispenser),

"aaa", "aba", "aca",

'a' , Blocks.cobblestone, 'b', new ItemStack(Items.bow, 1, OreDictionary.WILDCARD_VALUE), 'c', Items.redstone);

 

그림 3발사기 조합법(2)

 

 

참고 자료

http://greyminecraftcoder.blogspot.com.au/2015/02/recipes.html

+ Recent posts