강의 환경 : forge-1.8.9-11.15.1.1855

1.8.9에서 작성된 강의이지만, NBT를 다루는 개념은 다른 버전과 동일합니다. 단, 텍스처(texture)와 관련된 부분은 완전히 다르니 적절히 코드를 수정하시길 바랍니다.

 

배경 지식

  1. 기본 아이템
  2. 아이템 이벤트 함수
  3. NBT
  4. 아이템 스택

강의목표

  1. NBTTagCompound를 아이템 스택(Item Stack)에 대해 사용하는 방법을 익힌다.

 

1. NBT(Named Binary Tag)

NBT는 마인크래프트에서 데이터를 저장하기 위한 파일에 쓰이는 자료 형식입니다. 다양한 이름표(tags)로 이루어진 트리(tree) 구조를 띄도록 설계 되었습니다. 각 이름표는 다양한 자료형의 데이터를 담을 수 있습니다. 가능한 자료형은 int, float과 같은 숫자부터 String, List, Compound(hash)까지 다양합니다. 트리 구조라는 것은 하나의 이름표가, 또 다른 이름표들을 계층적으로 담을 수 있다는 의미입니다.

여러 기능을 모드에 추가하다 보면 아이템에, 정확히는 아이템 스택에, 정보를 저장해야 할 일이 생깁니다. 모드를 처음 만들기 시작하는 사람들은 종종 아이템 클래스 내부에 멤버 변수를 만들어 문제를 해결하려고 합니다. 하지만 이런 접근은 완전히 잘못된 접근입니다. 왜냐하면 아이템 객체는 모든 아이템 스택이 공유하기 때문입니다. 따라서 데이터를 저장하기 위해서는 아이템 스택에 NBT의 형태로 정보를 저장해야 합니다.

그림 2 객체 표현도

아이템 스택(Item Stack)의 NBT는 항상 Compound의 자료형을 가집니다. Compound는 해쉬(Hash) 구조를 가지고 있어서 문자열(String) 키(Key)를 이용해서 다양한 NBT를 값(Value)으로 저장할 수 있습니다. 때문에 Compound가 가지는 모든 키(Key)는 유일 해야 합니다. 만약 같은 키를 가진 값이 입력되면 덮어쓰게 됩니다.

 

2. NBT를 사용하는 아이템 만들기

이번 강의에서는 특정 좌표를 지정해서 귀환할 수 있는 아이템을 만들어 보도록 하겠습니다. Shift + 우클릭을 하면 현재 좌표가 아이템의 NBT에 저장이 되고, 이후 우클릭을 하면 저장된 위치로 이동합니다. 본 예제에서는 NBT를 쓰고, 읽는 것과 더불어서 엔티티(Entity)를 조작하는 것 또한 부가적으로 다뤄집니다.

먼저 귀환석(ItemTelepoter)의 아이템 클래스를 작성합니다. 지난 강의에서 다뤘던 족집게(ItemTweezer)와 뼈대가 상당히 비슷하니 참고하시길 바랍니다.

ItemTeleporter.java

package oortcloud.basictutorial.item;

 

import net.minecraft.creativetab.CreativeTabs;

import net.minecraft.item.Item;

import net.minecraftforge.fml.common.registry.GameRegistry;

 

public class ItemTeleporter extends Item {

 

    public ItemTeleporter() {

     this.setMaxStackSize(1);

this.setCreativeTab(CreativeTabs.tabTools);

this.setUnlocalizedName("teleporter");

GameRegistry.registerItem(this,"teleporter");

    }    

}

이제 언어(Language) 파일과 텍스처(Texture) 및 모델(Model)을 추가해서 기본적인 틀을 갖추어 보도록 하겠습니다. 1.8.9 버전을 기준으로 하기 때문에, 이 부분에서 지난 강의들과 차이가 있습니다. 이곳을 확인하세요. 언어 파일은 동일합니다. ModItems 또한 적당히 작성해 주시면 됩니다.

그림 3 아이템 뼈대 적용

 

 

3. NBT를 사용하여 기능을 구현하기

이제 이벤트 함수에 NBT를 이용해서 아이템에 좌표를 저장하고, 저장된 좌표로 순간이동을 하는 코드를 작성해보도록 하겠습니다. 아이템을 손에 들고 우 클릭 했을 때 호출되는 이벤트 함수는 onItemRightClick ()입니다.

public ItemStack onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn)

ItemStack itemStack

사용된 아이템 스택(Item Stack)입니다.

World worldIn

아이템 스택(Item Stack)이 사용된 세계(World) 객체입니다.

EntityPlayer playerIn

아이템 스택(Item Stack)을 사용한 플레이어(Player)입니다.

반환

아이템 스택(Item Stack)이 사용되고 난 후의 아이템 스택(Item Stack)이 반환됩니다.

 

ItemTeleporter.java

    @Override

    public ItemStack onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn) {

 

        if (worldIn.isRemote)

            return itemStackIn;

 

        if (playerIn.isSneaking()) {

            // Shift + RC

        } else {

            // RC

        }

        

        return itemStackIn;

    }

 

가장 먼저 코드가 서버(Server)에서만 실행될 수 있도록 클라이언트(Client)에서 실행되면 바로 반환하게 했습니다. 아이템의 NBT는 서버에서 수정이 이뤄지면 자동으로 클라이언트로 전달되기 때문에, 서버에서만 수정하는 것이 바람직하기 때문입니다. 엔티티(Entity)의 정보를 수정하는 것도 마찬가지 입니다.

isSneaking()이라는 함수를 이용해서 Shift를 누른 상태인지 확인하였습니다. 이제 각 경우에 맞추어 기능을 구현하겠습니다.

 

Shift+우 클릭을 하는 경우 플레이어의 좌표를 Compound에 "xpos", "ypos", "zpos"라는 이름으로 저장하고, 그것을 다시 아이템 스택에 저장하는 코드입니다. BlockPos는 1.8에서 추가된 개념이며 1.7.10에서는 각 좌표를 직접 플레이어 객체에서 가져오면 됩니다.

ItemTeleporter.java

    // Shift + RC

    NBTTagCompound tag = new NBTTagCompound();

    BlockPos pos = playerIn.getPosition();

    tag.setInteger("xpos", pos.getX());

    tag.setInteger("ypos", pos.getY());

    tag.setInteger("zpos", pos.getZ());

    itemStackIn.setTagCompound(tag);

 

우 클릭만 하는 경우 NBT를 아이템 스택에서 가져오고, 좌표가 저장되어 있으면 해당 좌표로 플레이어를 이동시킵니다.

ItemTeleporter.java

    // RC

    NBTTagCompound tag = itemStackIn.getTagCompound();

    if (tag != null && tag.hasKey("xpos") && tag.hasKey("ypos") && tag.hasKey("zpos")) {

        playerIn.setPositionAndUpdate(tag.getInteger("xpos"), tag.getInteger("ypos"), tag.getInteger("zpos"));

    }

 

추가적으로 여러 개의 좌표를 저장하거나, 메시지나 시각 효과를 연출하는 것도 좋은 연습이 될 것입니다.

 

원하는 대로 기능 구현이 잘 되었습니다.

 

참고자료

http://www.minecraftforge.net/wiki/Creating_NBT_for_items

http://minecraft.gamepedia.com/NBT_format

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

 

배경 지식

  1. 아이템 이벤트 함수
  2. 아이템 내구도

강의목표

  1. 아이템의 손상 값(Damage)을 이용하여 내구도를 가지는 아이템을 구현할 수 있다.
  2. 이벤트 함수를 이용하여 원하는 기능을 구현할 수 있다.

 

1. 아이템의 내구도(Durability)

내구도라는 것은 도구, 무기, 갑옷과 같이 유용한 기능을 하는 아이템들이 가진 속성입니다. 이 값은 아이템이 파괴되기 전까지 몇 번이나 더 기능을 해낼 수 있는지를 나타냅니다. 도구나 무기의 경우는 앞의 설명과 같이 남은 작동 횟수를 나타내고 갑옷은 조금 달라서 얼마만큼의 피해를 더 경감시킬 수 있는 지를 나타냅니다.

모든 아이템들의 잔여 내구도는 아이콘 아래 부분에 초록색 내구도 막대를 통해 확인 할 수 있습니다. 단, 한 번도 사용되지 않은 아이템은 막대가 그려지지 않습니다. 아이템이 손상될수록 막대의 길이가 짧아지고 색상 또한 붉은 색으로 변해갑니다. 내구도가 거의 다 소진 된 경우에는 내구도가 모두 소진된 것처럼 빈칸만이 그려지기도 합니다. 이것은 내구도가 픽셀의 크기에 맞춰져 그려지기 때문에 일어나는 현상입니다.

수치로서 존재하는 내구도는 게임 내에서 F3+H를 누르면 볼 수 있습니다. 이 옵션은 내구도 뿐만 아니라 몇몇 추가적인 설명(Tooltip)을 가방(Inventory)에서 제공합니다. 여기서 보이는 내구도 값은 실제 내구도보다 1이 작습니다. 왜냐하면 이 수치가 0이 되었을 때, 마지막으로 도구를 한 번 더 사용할 수 있기 때문입니다.

 

 

2. 내구도를 사용하는 아이템 만들기 – 족집게

이번 강의에서는 '족집게'를 만들어보며 도구 구현법을 익혀보도록 하겠습니다. 이 아이템은 닭에게 우 클릭을 통해 사용하면 깃털을 하나 얻고, 닭에게 1의 피해를 줄 수 있습니다. 본 예제를 통해서 내구도를 어떻게 다루는지, 이벤트 함수를 통해 다른 엔티티(Entity)와 어떻게 상호 작용하는지, 마지막으로 어떻게 아이템을 월드(World)에 떨어뜨리는 지 확인해보세요.

먼저 족집게의 아이템 종류를 결정할 아이템 클래스를 작성합니다. 이 클래스는 가위(ItemShears)를 바탕으로 작성됩니다. 참고하시면 도움이 되실 겁니다.

이번 족집게(ItemTweezer)는 해당 클래스에서 단 하나의 객체만 존재하는 싱글톤(Singleton)으로 작성합니다. 즉, 이 클래스에서 단 하나의 아이템 객체만이 생성되는 것을 가정하는 겁니다. 따라서 생성자 부분의 코드가 이전과는 조금 다릅니다. 이렇게 코드를 짜면 ModItems에서 아이템 객체를 생성하고 등록하는 과정이 훨씬 간단해진다는 장점이 있습니다.

ItemTweezer.java

package oortcloud.basictutorial.item;

 

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

import net.minecraft.creativetab.CreativeTabs;

import net.minecraft.item.Item;

 

public class ItemTweezers extends Item {

 

    public ItemTweezers() {

this.setMaxStackSize(1);

this.setMaxDamage(238);

this.setCreativeTab(CreativeTabs.tabTools);

this.setUnlocalizedName("tweezers");

this.setTextureName("basictutorial:tweezers");

GameRegistry.registerItem(this,"tweezers");

    }

    

}

이 아이템에서는 손상 값(Damage)이 내구도로 사용이 됩니다. 그렇게 때문에 여러 아이템이 겹쳐지게 되면 손상 값 데이터가 소실 될 수 있으므로, 반드시 setMaxStackSize (1)를 통해 최대 개수를 1개로 설정해야 합니다. 이 후 setMaxDamage(63)는 해당 도구의 최대 손상 값을 결정합니다. 내구도로 환산되면 64번 아이템을 사용할 수 있습니다. 생성자에서 바로 등록이 이뤄지고 이름을 생성자 밖에서 지정해줄 수 없으므로 생성자가 2번 이상 불리면 오류가 나게 됩니다.

이제 언어(Language) 파일과 텍스처(Texture)를 추가해서 기본적인 틀을 갖추어 보도록 하겠습니다.

en_US.lang

item.tweezers.name=Tweezers

ModItems는 이렇게 작성 되겠네요. 지난 강의의 코드도 함께 수록되어 있습니다.

ModItems.java

public final class ModItems {

    

    public static Item itemNumber;

    public static Item itemFortuneCookie;

    public static Item itemTweezers;

    

    public static final void init() {

        itemFortuneCookie = new ItemFortuneCookie().setUnlocalizedName("fortuneCookie").setCreativeTab(CreativeTabs.tabMisc).setTextureName("basictutorial:fortuneCookie");

        GameRegistry.registerItem(itemFortuneCookie, "fortuneCookie");

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

        GameRegistry.registerItem(itemNumber, "itemNumber");

        itemTweezers = new ItemTweezers();

    }

    

}

 

 

3. 내구도를 사용하는 아이템 만들기 – 족집게

이제 이벤트 함수를 이용해서 닭을 우 클릭하면 내구도가 소모되고, 깃털이 나오며, 동시에 닭에게 1의 피해를 주도록 해보겠습니다. 아이템으로 엔티티(Entity)를 우 클릭 했을 때 호출되는 이벤트 함수는 itemInteractionForEntity()입니다.

public boolean itemInteractionForEntity(ItemStack itemStack, EntityPlayer entityPlayer, EntityLivingBase entityLivingBase)

ItemStack itemStack

사용된 아이템 스택입니다.

EntityPlayer entityPlayer

아이템을 사용한 플레이어의 엔티티(Entity) 객체입니다.

EntityLivingBase entityLivingBase

플레이어가 우 클릭을 한 대상 엔티티(Entity)입니다.

반환

상호작용이 일어나면 true, 그렇지 않으면 false를 반환해야 합니다.

 

ItemTweezer.java

    @Override

    public boolean itemInteractionForEntity(ItemStack itemStack, EntityPlayer entityPlayer, EntityLivingBase entityLivingBase) {

        return false;

    }

 

이제 여기에 우리가 원하는 기능을 할 코드를 입력하면 됩니다. 기능을 구현하기 전에, 일반적으로 엔티티(Entity)를 생성하는 코드(아이템 드롭)는 서버에서만 실행 되야 합니다. 따라서 다음과 같이 코드를 작성하여 클라이언트에서는 코드가 실행되지 않도록 합니다.

엔티티는 서버에서만 관리되는 대상입니다. 서버에서만 엔티티를 생성해도 그것이 클라이언트로 바로 반영이 되고, 만약 양 쪽에서 모두 생성해버리면 클라이언트에서는 2개의 엔티티가 생성된 것처럼 보이게 됩니다.

ItemTweezer.java

    @Override

    public boolean itemInteractionForEntity(ItemStack itemStack, EntityPlayer entityPlayer, EntityLivingBase entityLivingBase) {

        if (entityPlayer.worldObj.isRemote) {

            return false;

        }

        // IMPLEMENT HERE, 구현은 이곳에 하세요

        return false;

    }

 

이제 기능 구현에 필요한 코드를 입력하겠습니다. 주석을 참조하세요. 아래 코드에서 핵심은 damageItem ()이라고 할 수 있습니다. 이 함수가 결국 내구도를 소모시키기 때문입니다.

ItemTweezer.java

    @Override

    public boolean itemInteractionForEntity(ItemStack itemStack, EntityPlayer entityPlayer, EntityLivingBase entityLivingBase) {

        if (entityPlayer.worldObj.isRemote) {

            return false;

        }

        if (entityLivingBase instanceof EntityChicken) {

            // entityLivingBase 닭인지 확인합니다.

            

            if (entityLivingBase.getHealth() > 1.0F) {

                // 대상의 체력이 1보다 높을 때만 동작합니다. , 도구를 이용한다 해도 대상이 죽지는 않습니다. 죽기 전까지 털이 뽑힐 .

                

                // 아이템을 드롭하는, 자주 쓰이는 코드입니다.

                Random rand = new Random();

                // 임의의 방향으로 아이템이 튕겨 지도록 랜덤 객체를 만듭니다.

                EntityItem ent = entityLivingBase.entityDropItem(new ItemStack(Items.feather), 1.0F);

                // entityLivingBase 깃털의 EntityItem ent 떨어뜨리도록 하고, y 기본 속도를 1.0으로 설정합니다.

                ent.motionY += rand.nextFloat() * 0.05F;

                ent.motionX += (rand.nextFloat() - rand.nextFloat()) * 0.1F;

                ent.motionZ += (rand.nextFloat() - rand.nextFloat()) * 0.1F;

                // 임의의 속도를 부여합니다.

                

                

                entityLivingBase.attackEntityFrom(DamageSource.causePlayerDamage(entityPlayer), 1.0F);

                // entityLivingBase에게 플레이어(entityPlayer)로부터 피해를 1 받도록 합니다.

                

                itemStack.damageItem(1, entityLivingBase);

                // 내구도를 1 소모시킵니다.

                

                return true;

            }

        }

        return false;

    }

 

원하는 대로 기능 구현이 잘 되었습니다.

 

참고자료

http://minecraft.gamepedia.com/Item_durability

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

 

배경 지식

  1. 기본 모드 파일
  2. 기본 아이템
  3. 서버와 클라이언트

 

강의목표

  1. 사건 기반 프로그래밍(Event-driven Programming, EDP)의 원리를 이해한다.
  2. 아이템 클래스의 이벤트 함수 각각을 이해한다.
  3. 원하는 기능을 구현하는 아이템을 만들 수 있다.

 

1. 사건 기반 프로그래밍(Event-driven Programming, EDP)

이 단락은 아이템의 동작에 대한 보충 설명이므로 굳이 읽지 않으셔도 됩니다.

사건 기반 프로그래밍은 사용자의 행동(마우스, 키보드 입력)이나 다른 프로그램이 보낸 메시지와 같은 '사건(Event)'에 따라 프로그램의 동작을 결정하는 프로그래밍 패러다임(Paradigm)입니다. 이러한 EDP(Event-driven Programming)는 주로 GUI나 사용자의 입력에 반응하는 것이 주 기능인 프로그램들에 사용됩니다. 주요 반복문(Main Loop)이 이벤트를 인식하고 관련된 함수를 호출하는 방식으로 구현됩니다.

마인크래프트의 아이템도 사건 기반 프로그래밍에 기반하여 동작합니다. 사용자가 아이템으로 무엇을 하냐에 따라서 아이템의 기능을 구현하는 것입니다. 예를 들어 아이템을 버리고, 세계(World)와 상호작용할 때마다 특수한 함수가 불려집니다. 개발자는 Item 클래스 내부의 이벤트 함수를 오버라이드하여 이러한 기능들을 조작할 수 있습니다.

 

 

2. 예시를 통한 개념 학습 – 포춘 쿠키(Fortune Cookie)

이번 단락에서는 아이템을 사용할 때 오늘의 운세를 출력하는 간단한 아이템을 만들어 보겠습니다. 포춘 쿠키라는 이 아이템은 우 클릭으로 사용하면 하나가 소모되고 채팅 창에 임의의 운세를 출력합니다. 크리에이티브 모드인 경우에는 소모되지 않도록 하겠습니다. 본 예시를 통해서 이벤트 함수를 어떻게 조작하는지 유심히 살펴보시고 지금까지 다뤄왔던 내용들을 복습하는 시간을 가지시길 바랍니다. 또한 실제 구현에서 자주 사용되는 함수들을 따로 강조해 드리겠습니다

1) 아이템 틀 만들기

지난 강의에서처럼 기능을 구현해야하기 때문에 Item을 상속하는 클래스를 만듭니다. 그리고는 이 클래스에는 추가적인 코드없이 기본 과정을 따라 등록해보도록 합시다. 텍스처는 이것을 이용하겠습니다.

ItemFortuneCookie.java

public class ItemFortuneCookie extends Item {

 

}

 

ModItems.java

public final class ModItems {

    

    public static Item itemFortuneCookie;

    

    public static final void init() {

        itemFortuneCookie = new ItemFortuneCookie().setUnlocalizedName("fortuneCookie").setCreativeTab(CreativeTabs.tabMisc).setTextureName("basictutorial:fortuneCookie");

        GameRegistry.registerItem(itemFortuneCookie, "fortuneCookie");

    }

    

}

 

en_US.lang

item.fortuneCookie.name=Fortune Cookie

 

그림 1 등록을 마친 아이템

 

2) 이벤트 함수 오버라이드

이제 우 클릭을 할 때 호출되는 함수를 오버라이드하여 기능을 구현하도록 하겠습니다. 이벤트 함수는 일반적으로 'on'으로 시작하고 주석 처리가 잘 되어 있어서 어떤 기능인지 확인하기는 용이합니다. onItemRightClick이라는 메소드(Method)는 아이템을 들고 우 클릭을 하는 모든 경우에서 호출됩니다. 플레이어의 손에 들린 아이템 스택, 플레이어가 속한 세계(World), 그리고 플레이어의 객체를 인자로 넘겨 받습니다. 그리고 다시 해당 아이템 스택을 반환합니다. 이 메소드는 클라이언트와 서버 모두에서 실행됩니다.

ItemFortuneCookie.java

@Override

public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

 

    return itemStack;

 

}

 

먼저 플레이어에게 채팅 메시지를 출력하는 메소드를 살펴보겠습니다. 채팅 메시지는 player.addChatComponentMessage(IChatComponent msg)를 호출하여 출력합니다. IChatComponent 인터페이스를 반드시 구현할 필요는 없으며 단순한 문자 출력이 목적이라면 new ChatComponentText(String text)를 이용해서 간단히 객체를 생성할 수 있습니다. 그러면 간단한 메시지를 출력해보도록 하겠습니다

ItemFortuneCookie.java

@Override

public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

 

    player.addChatComponentMessage(new ChatComponentText("Example Message"));

 

    return itemStack;

}

그림 2 2번 출력되는 메시지

아이템을 한 번만 사용해도 메시지가 2번 출력됩니다. 앞서 말했듯이 addChatComponentMessage 가 클라이언트와 서버 모두에서 실행되기 때문에 일어나는 문제입니다. 클라이언트에서 addChatComponentMessage 가 호출되면 바로 채팅창에 출력되고, 서버에서 호출되면 클라이언트로 해당 메시지를 전송합니다. 이 기능은 플레이어에게 메시지를 출력하는 것이 목적이므로 클라이언트에서만 메시지를 출력하도록 바꾸어 보도록 하겠습니다.

World 클래스에 존재하는 isRemote라는 멤버 변수는 클라이언트 세계면 true, 서버 세계면 false의 값을 가집니다. 따라서 다음과 같이 코드를 작성하면 클라이언트에서만 코드가 실행되며 문제가 해결됩니다.

ItemFortuneCookie.java

@Override

public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

 

    if (world.isRemote) {

        player.addChatComponentMessage(new ChatComponentText("Example Message"));

    }

 

    return itemStack;

}

 

본래의 목적은 임의의 메시지를 출력하는 것이므로 코드를 조금 추가 하겠습니다. 내용은 아이작의 구속에 나오는 운세들입니다. EntityLivingBase 클래스에는 Random 객체를 반환하는 getRNG()라는 메소드가 있습니다. 이 객체를 이용해서 임의의 값을 획득하는게 가능합니다. EntityPlayer 클래스가 EntityLivingBase의 하위 클래스이기 때문에 해당 메소드를 호출할 수 있습니다.

ItemFortuneCookie.java

public static String[] fortune = {"BRING HIM THE PHOTO", "YOU WILL DIE ALONE", "YOU ARE THROWING YOUR LIFE AWAY", "GO OUTSIDE!", "ASK AGAIN LATER", "THINK FOR YOURSELF", "QUESTION AUTHORITY", "YOU ARE WORSHIPING A SUN GOD", "DON'T LEAVE THE HOUSE TODAY", "GIVE UP!", "MARRY AND REPRODUCE", "STAY ASLEEP", "WAKE UP", "WE WILL ALL DIE ONE DAY", "LOOK TO LA LUNA", "STEVEN LIVES ", "MEET STRANGERS WITHOUT PREJUDICE", "A HANGED MAN WILL BRING YOU NO LUCK TODAY", "WHAT DO YOU WANT TO DO TODAY?", "YOU ARE DARK INSIDE", "HAVE YOU SEEN THE EXIT?", "GET A BABY PET IT WILL CHEER YOU UP", "YOUR PRINCESS IS IN ANOTHER CASTLE", "YOU ARE PLAYING IT WRONG GIVE ME THE CONTROLLER", "TRUST GOOD PEOPLE", "LIVE TO DIE", "WHEN LIFE GIVES YOU LEMONS REROLL!"};

 

@Override

public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

 

    if (world.isRemote) {

        player.addChatComponentMessage(new ChatComponentText(fortune[player.getRNG().nextInt(fortune.length)]));

    }

 

    return itemStack;

}

 

마지막으로 아이템의 개수를 하나 감소시키는 과정을 추가하도록 하겠습니다. 이때 일반적으로 크리에이티브 모드에서는 아이템이 소모되지 않도록 합니다. 아이템 스택의 stacksize 변수가 개수를 나타냅니다. player.capabilities.isCreativeMode는 플레이어가 크리에이티브 모드이면 true, 아니면 false의 값을 가집니다. 아이템 스택의 개수가 0이 되면 onItemRightClick을 호출한 코드가 알아서 인벤토리에서 해당 아이템을 삭제합니다. 지금 추가된 구문은 아이템을 소모시킬 때 널리 사용됩니다.

ItemFortuneCookie.java

@Override

public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

 

    if (!player.capabilities.isCreativeMode) {

        --itemStack.stackSize;

    }

 

    if (world.isRemote) {

        player.addChatComponentMessage(new ChatComponentText(fortune[player.getRNG().nextInt(fortune.length)]));

    }

 

    return itemStack;

}

그림 3 완성본

이렇게 해서 포춘 쿠키가 완성 되었습니다. Item 클래스 내의 이벤트 함수들에 대한 구체적인 정보도 따로 정리하여 올리겠습니다.

 

 

참고자료

https://en.wikipedia.org/wiki/Event-driven_programming

http://bindingofisaac.wikia.com/wiki/Fortune_Telling_Machine

http://bedrockminer.jimdo.com/modding-tutorials/advanced-modding/modding-tips-and-tricks/#chatSP

https://en.wikipedia.org/wiki/Fortune_cookie

+ Recent posts