Tictim과 함께하는 마인크래프트 모딩 101

단편-1. I18n


※ 이 강좌는 1.10 ~ 1.11버전을 기준으로 작성됩니다.


틱팀입니다.

오늘은 모 지인 분께서 I18n에 대한 이해도가 아주 테러블한 것을 보고 충격을 받아서 I18n에 대한 짧은 설명과, 자세한 사용법을 알려드리도록 하겠심미다.


1. 현지화란?


현지화(Localization)란, 프로그램을 여러 문화권의 사람들이 사용할 수 있도록 지원하는 것을 의미합니다. 마인크래프트에서는 주로 번역을 가리키죠.


마인크래프트에서 번역을 하는 원리는 다음과 같습니다. lang 파일이라는 문자열 두 개를 =으로 묶어 놓은 문자열의 쌍으로 이루어진 텍스트 파일이 있습니다. 게임에서 설정된 언어에 따라서 lang 파일을 읽어 문자열의 쌍을 저장해 둡니다.

그리고 특정한 클래스에서 번역될 문장의 키 값을 입력하면, 첫 번째 문자열이 키 값과 일치하는 문자열 쌍을 찾아 그 쌍의 두 번째 문자열을 반환합니다.

사진으로 설명하면 이렇습니다.


2. I18n


마인크래프트에서 번역을 지원하는 클래스는 두 종류가 있습니다. 둘 다 비슷한 방식으로 작동하긴 합니다. 하나는 I18n, 다른 하나는 I18n입니다.


..

..

네. 똑같은 이름의 클래스가 두 개나 있습니다. 하는 일은 똑같지만 알아둬야 할 차이점이 있으니 숙지하세요.


 

(Client-Sided)

I18n

[ net.minecraft.client.resources.I18n ]

(Deprecated)

I18n

[ net.minecraft.util.text.translation.I18n ]

서버에서 존재

 아니오

 예

포매팅 없는 번역

 불가

 가능

Fallback(영어 고정) 번역

 지원 안 함

 지원


어째 client.resources.I18n이 더 구려 보입니다. 말만 Deprecated지, 바닐라에서도 특수한 상황이 아니면 util.text.translation.I18n을 씁니다. 클라이언트에서만 존재한다는 게 꽤나 큰 제약이거든요. 그런 이유로 여러분도 후자를 더 많이 쓰게 될 겁니다.


여담이지만 client.resources.I18n에서는 포매팅 없는 번역을 아주 쉽게 구현 가능한데, 이를 하지 않은 이유가 매우 궁금해집니다. 그냥 발로 만들어 버린 걸까요. 모르겠습니다.



이번에는 I18n 클래스의 접근 가능한 함수들을 알아봅시다. 함수를 알아야 쓰죠. 그렇죠?

먼저 util.text.translation.I18n을 알아봅시다.


@Deprecated public static String translatedToLocal(String)

문자열을 번역합니다. 위에서 봤던 사진처럼, 키 값을 대응되는 문자열로 반환합니다.

대응되는 문자열이 없을 시 키 값을 그대로 반환합니다.


@Deprecated public static String translatedToLocalFormatted(String, Object...)

문자열을 번역하고, 그 결과물을 포매팅합니다. String#format을 사용합니다.

대충 이런 방식으로 작동합니다. 번역된 문자열을 키 값으로 해서 포매팅을 합니다.

포매팅 과정에서 예외가 일어나면, "Format error: "+(번역된 키 값)을 반환합니다.


@Deprecated public static String translatedToFallback(String)

쓸 데는 거의 없을 겁니다. 문자열을 en_us, 즉 영문으로 번역합니다.


@Deprecated public static boolean canTranslate(String)

I18n이 해당 키 값에 대응되는 문자열을 가지고 있는지 반환합니다. 역시 쓸 데는 거의 없을 겁니다.


@Deprecated public static long getLastTranslationUpdateTimeInMilliseconds()

I18n이 가장 최근에 업데이트된 시간을 밀리초 단위로 반환하는 것 같습니다. 쓸 데는 없습니다. 바닐라에서도 단 한 곳에서 I18n이 업데이트되었는지 여부를 체크할 때 쓰며, 이외에는 쓰이는 곳이 없습니다.


예제입니다. 강좌 2편에서 "item.item_first.name"을 "첫 번째 아이템"으로 지정한 lang파일을 그대로 사용합니다.


formattedName이라는 키를 하나 더 추가했습니다.


다음과 같은 구문을 preInit, init 아니면 아무 데에나 집어넣어 실행시켜 봅시다.


짜잔


이번에는 client.resources.I18n을 알아봅시다.


public static String format(String, Object...)

문자열을 번역하고, 그 결과물을 포매팅합니다. String#format을 사용합니다.

이전 클래스의 translatedToLocalFormatted와 같은 기능입니다.


public static boolean hasKey(String)

I18n이 해당 키 값에 대응되는 문자열을 가지고 있는지 반환합니다.

이전 클래스의 canTranslate와 같은 기능입니다.


이번에는 이 클래스를 사용하여 번역해 봅시다. 서버에서는 존재하지 않기 때문에, 저 문장은 프록시에서 실행해야 합니다. 클라이언트에서는 잘 돌아가니 결과물 나오는 것만 보고 지우도록 합시다.


짜잔


1.7에서는 net.minecraft.util.text.translation.I18n없습니다!

그 대신 똑같은 기능을 포함하는 StatCollector [ net.minecraft.util.StatCollector ] 라는 클래스가 있습니다. 그냥 이름하고 패키지만 바뀐 같은 클래스여서 다른 설명은 필요는 없을 듯 합니다.

net.minecraft.client.resources.I18n은 멀쩡히 존재합니다.



3. TextFormatting


TextFormatting [ net.minecraft.util.text.TextFormatting ] 은 마인크래프트의 텍스트 렌더러에게 주는 사인 같은 겁니다. 이걸로 글씨의 색깔을 하얗게 하거나 빨갛게 하거나 기울이거나 밑줄을 긋거나..하는 일이 가능합니다.


마인크래프트의 포매팅은 16개의 색깔과 6개의 포맷 코드를 지정할 수 있습니다. 아니, 포맷 코드 중 하나는 초기화 코드이니 사실상 5개일까요?


모든 포매팅들은 \u00a7(§)라는 문자 뒤에 한 글자를 붙인 식으로 되어 있습니다. String#format의 %s %d %f 등의 사인과 같이 말이죠.


마인크래프트가 문자열을 렌더링할 때 포매팅 코드를 읽으면, 다음부터 출력되는 문자들에 포매팅 코드에 따른 처리를 해 줍니다. 예를 들어 붉은 색을 입히는 코드 §c가 들어간 "§c빨간색"이라는 문자열을 렌더링한다면, §c를 읽은 뒤의 문자열에 붉은 색을 입혀서 결과물은 "빨간색"이 됩니다.


색깔 코드는 0부터 f까지의(16진수) 모든 글자를 붙여서 만들 수 있으며, 각각 이렇게 됩니다.

§0 -> Black

§1 -> Dark Blue

§2 -> Dark Green

§3 -> Dark Aqua

§4 -> Dark Red

§5 -> Dark Purple

§6 -> Gold

§7 -> Gray

§8 -> Dark Gray

§9 -> Blue

§a -> Green

§b -> Aqua

§c -> Red

§d -> Light Purple

§e -> Yellow

§f -> White


포맷 코드는 k, l, m, n, o, r이 존재하며, 다음과 같습니다.

§k -> 난독화. 글자를 그릴 때마다 임의의 글자를 그려서 정신없이 바뀌는 문장을 만듭니다(..)

§l -> 볼드체(굵게)

§m -> 취소선

§n -> 밑줄

§o -> 이태릭(기울임꼴)

§r -> 모든 포매팅 해제


이것들을 응용해보자면, "§c§l빨간색§r검은색"이라는 문장을 렌더링하면 "빨간색검은색"이 됩니다.


예제입니다. 우리 두 번째 아이템의 이름을 노랗게 물들여 봅시다.


짜잔



포매팅을 사용할 때 주의할 점이 있습니다. 색깔 코드를 입력받으면, 이전에 가지고 있던 포맷 코드는 사라진다는 점입니다.

예를 들어 "§o기울임체§c빨간색"이라는 글자를 그릴 때, 기울임체까지는 정상적으로 적용되지만 §c를 읽어들일 때 기존에 가지고 있던 §o에 대한 기록을 날려버리기 때문에 "기울임체빨간색"처럼 되어 버립니다.

붙어 있어도 마찬가지입니다. "§o§c기울임체와 빨간색"이라는 글자를 그릴 때, 기울임체 바로 다음 들어온 빨간색이 기울임체를 먹어 버리기 때문에 "기울임체와 빨간색"이 됩니다.

첫 번째 문장의 에러를 해결하려면  "§o기울임체§c§o빨간색"처럼 색깔 코드 이후 적용할 포맷 코드를 다시 입력해 주셔야 합니다. 두 번째 문장의 에러를 해결하려면, 순서를 바꿔 "§c§o기울임체와 빨간색"처럼 색깔을 맨 먼저 입력해 주셔야 합니다. 


그리고 TextFormatting [ net.minecraft.util.text.TextFormatting ] 이라는 이름의, 모든 포매팅 코드를 열거형으로 나열해 놓은 enum 클래스가 있습니다. 이것들은 toString()으로 변환하면 각각의 포매팅 코드가 됩니다. 예를 들어, TextFormatting.DARK_BLUE.toString()은 짙은 파란색으로 색깔을 바꾸는 코드 "§1"과 같습니다.


+

포매팅 코드 §를 빠르게 그리는 초간단 방법!

Alt 누르고 넘버 패드에서 0167. 참 쉽죠?



1.7에서는 TextFormatting이 존재하지 않습니다!

대신 EnumChatFormatting [ net.minecraft.util.EnumChatFormatting ] 이 이름과 패키지만 바뀐 채 똑같은 기능을 지원합니다.





공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]


Posted by Tictim indie.

Tictim과 함께하는 마인크래프트 모딩 101

2. 블럭, 아이템 그리고 모델


※ 이 강좌는 1.10 ~ 1.11버전을 기준으로 작성됩니다.


다시 돌아왔습니다. 틱팀입니다.

이 강좌도 1화처럼 쓰는 데 한세월 걸릴지도 모르겠습니다. 안 그랬으면 좋겠습니다만 말입니다.



1. 아이템


간단한 아이템을 만들어 봅시다. 하나는 평범한 아이템, 하나는 우클릭하면 stdout으로 로그를 출력하는 아이템을 말이죠.


먼저, 아이템을 public static final field의 형태로 보관할 클래스를 만듭니다.

이름은 아무거나 해도 되지만 "Items"는 추천드리지 않습니다. 바닐라에 이미 동명의 클래스가 존재하기 때문에 하나를 임포트하면 다른 하나를 임포트할 수 없게 되는 기묘한 일이 벌어집니다.

저는 메인 패키지에 Contents라는 이름으로 클래스를 자주 만듭니다. 사실 이는 모더마다 많이 다릅니다. 서브 패키지에 클래스를 만든다던지. 어느 쪽이 보편적이냐고 물으시면 제 쪽이 많이 후달리는 느낌?(..)

아무튼, 이 클래스는 인스턴스를 생성할 필요도 상속을 받을 필요도 없으니 final class에 생성자도 private로 해 놓읍시다.


그리고, 이런 형태로 Item 필드를 만들어줍시다. 이 Item이 평범한 첫 번째 아이템이 될 겁니다.

Item [ net.minecraft.item.Item ] 클래스는 이름에서 알 수 있듯이 모든 Item 클래스의 어미 클래스이며, 별 다른 하는 일이 없는 단순한 아이템입니다.


하지만 아이템을 등록하려면 몇 가지 필요사항을 거쳐야 하며, 추가적으로 거치면 좋은(?) 사항들도 있습니다.

 setRegistryName(String name)

 필수적인 사항입니다. 마인크래프트에서 아이템에 관한 정보를 관리할 때 쓰입니다. 소문자만으로 지정하는 것이 좋습니다.

 setUnlocalizedName(String name)

 편하게 아이템의 이름을 지정할 수 있는 메소드입니다. [item.***.name] 식으로 표시됩니다.

 setCreativeTab(CreativeTabs tab)

 편하게 크리모드 탭을 지정할 수 있는 메소드입니다.



이 메소드들은 모두 Item 형태의 자기 자신을 반환합니다. 따라서 저런 사슬 형태의 코드를 통해 한 줄에 한 아이템을 만들고 기본적인 정보까지 맞춰 놓을 수 있습니다.


이제 모드 클래스로 돌아가 봅시다. 저번에 pre-Init, init, post-Init에서 로그를 출력해 봤었죠. pre-Init로 가 봅시다. 비밀결사 어쩌구를 출력했던 곳으로요.


그리고, 이 코드를 추가해 주시면 됩니다.

GameRegistry [ net.minecraftforge.fml.common.registry.GameRegistry ] 에서는 아이템, 블럭, 월드젠, 타일엔티티 등을 게임에 등록시킬 수 있는 클래스입니다. 그리고 register 메소드는 아이템과 블럭을 등록시킵니다. 여기서는 아이템을 등록시키죠.


한 번 런쳐를 실행해 봅시다. 모델을 지정해 주지 않아 와꾸가 빻아 버린 모습입니다만, 어쨌든 아이템은 만들어졌습니다. 이름도 이상합니다. item...뭐? 아무튼.

모델과 이름은 아래에서 만들 예정입니다. 그러면 두 번째 아이템으로 넘어가죠.



특수한 일을 하는 Item의 경우 따로 메소드를 받아 처리해 줘야 합니다. 메소드를 받으려면 메소드를 상속해야 하고, 그러려면 Item을 상속하는 새 클래스를 만들어야겠죠.

일단 클래스를 만들기 이전에, 만들어 뒀던 모드 클래스가 위치하는 패키지 아래에 item이라는 서브 패키지를 만듭시다. 여기에 만드는 모든 Item 클래스를 집어넣으시면 됩니다. 정리가 최고예요.


그리고 그 안에 ItemSecond라는 이름의 클래스를 새로 만듭니다.


Item을 상속하게 해 주세요.


+

이 강좌에 나오는 클래스의 이름은 바꾼다고 해도 작동 여부와 큰 관련은 없긴 합니다. 하지만 그래도 이름을 지을 때 최소한의 규칙은 지켜 주시는 것이 좋습니다. 남한테 좋은 게 아니라 바로 당신에게 좋습니다.

클래스를 상속할 때, 예를 들면 이 Item같은 클래스를 상속할 때는 이름 앞에 부모 클래스의 이름을 붙여 주시는 것이 좋습니다. ItemBucket, ItemSnowball처럼요.

가나다순 정렬로도 이쁘게 나오고, 무엇보다 엄마 아빠 클래스가 누군지 한 눈에 보입니다. ItemAAA와 BlockAAA가 모두 AAA라는 이름이었다고 한다면 누가 블럭이고 누가 아이템인지 어떻게 알아요?


조금 코드를 짜 본 모습입니다.


NOTE 1 - Contents에서 ITEM_FIRST에서 호출했던 세 개의 메소드입니다. 밖에서 호출할 수 있으니 당연히 생성자에서도 호출할 수 있겠죠.

NOTE 2 - 해당 메소드는 아이템을 우클릭했을 때 호출되는 메소드입니다. 여기에 로그를 출력시키는 코드를 넣으면, 우클릭할 때 로그가 나오게 됩니다.

NOTE 3 - 아이템과 월드의 상호작용에 쓰이는 값입니다. 지금은 그냥 넘기셔도 됩니다.


두 번째 아이템도 Contents에 추가해서 인스턴스를 만들어 줍시다. 생성자에서 이미 setRegistryName을 비롯한 3개의 메소드를 호출한 상태이기에 첫 번째와 같이 메소드를 호출하지는 않아도 됩니다.


*

더 정확히 말하자면 호출하지 말아야 합니다. setRegistryName은 두 번 설정하려 하면 오류를 터트립니다.


그리고 두 번째 아이템도 preInit에서 등록해 주세요.


이러면 두 아이템 모두 인게임에서 나오게 됩니다. 들고 우클릭하면 로그도 잘 출력됩니다. 그런데 두 번 호출되네요?

로그가 두 번 호출되는 이유는 클라이언트에서 서버가 하는 일을 따라하기 때문입니다. 로그를 출력하는 걸 따라하는 게 아니라 플레이어가 아이템을 들고 우클릭하는 것을 따라 같은 메소드를 호출하고, 별다른 처리를 안 했기에 같은 줄이 동시에 두 번 호출된 겁니다. 로그를 보시면 하나는 서버 스레드, 하나는 클라이언트 스레드에서 터지고 있죠?


이를 방지하기 위해서는 world#isRemote를 참조하시면 됩니다.

World net.minecraft.world.World ] 는 플레이어가 있는 월드입니다. 블럭, 타일엔티티, 엔티티 등등을 가지고 있죠. 그리고 isRemote 필드는 이 월드가 서버를 따라하는 종속된 월드인지 여부를 가지고 있습니다. 즉 true면 클라이언트 월드, false면 서버 월드라고 생각하시면 됩니다.

여기서는 값을 뒤집어서 서버일 때만 로그가 출력되도록 만들었습니다.


정말로 완성입니다. 아이템 끝!


+

1.10 버전에서는 ItemStack(아이템과 스택 수, 대미지값, NBT 등등을 모두 핸들링하는 클래스) 인스턴스의 취급 방법이 약간 다릅니다. ItemStack 자체의 작동 방식도 다르고요. 따라서 1.10에서 해당 코드를 작성한다면..

이렇게 되겠습니다. 함수에 전달되는 인자가 약간 바뀌었습니다. 그 외에는...실수로 SUCCESS를 PASS로 바꿔 버리긴 했지만(...) 이외에 다른 점은 없습니다.


다른 버전에서 개발하실 때면, 앞으로 맞아떨어지는 함수가 없는 사태가 종종 발생하실 겁니다.

그럴 때는 컨트롤+F키를 이용해 이름이 맞는 함수를 대신 상속해서 코드를 짜시면 됩니다.



2. 블럭


블럭 또한 간단하게 만들어 봅시다. 이번에도 하나는 그냥 블럭, 하나는 우클릭하면 로그가 출력되는 블럭으로 말입니다.


편의상 전에 만들어 둔 아이템 담아두는 곳에 블럭 인스턴스를 만들도록 합시다. Block [ net.minecraft.block.Block ] 은 Item과 같이 모든 블럭의 어미 클래스이며, 별 다른 하는 일이 없는 평범한 블럭입니다.

생성자의 인자로 받는 Material [ net.minecraft.block.material.Material ] 은 지도에서 표시되는 색깔부터 시작해서 히트박스 유효 검사, 도구 사용 여부 등등 오만 가지 사항에 쓰이며, Material 클래스에 전부 public static final field의 형태로 존재합니다. 저는 나무로 넣어 주겠습니다.


아이템과 비슷하게 블럭 또한 등록을 위해서는 필요사항을 거쳐야 합니다.

 setRegistryName(String name)

 필수적인 사항입니다. 마인크래프트에서 블럭에 관한 정보를 관리할 때 쓰입니다. 소문자만으로 지정하는 것이 좋습니다.

 setUnlocalizedName(String name)

 편하게 블럭의 이름을 지정할 수 있는 메소드입니다. [tile.***.name] 식으로 표시됩니다.

 setCreativeTab(CreativeTabs tab)

 편하게 크리모드 탭을 지정할 수 있는 메소드입니다.

하는 방법은 아이템과 거의 똑같습니다.


그리고 모드 클래스로 돌아가, 다음 코드를 추가해 줍시다.

GameRegistry의 register(...) 메소드는 앞에서 말씀드렸다시피 블럭 또한 등록할 수 있습니다.


그리고 아래에 ItemBlock [ net.minecraft.item.ItemBlock ] 인스턴스를 생성해서 등록합니다.

ItemBlock은 Item의 하위 클래스로, 블럭을 받는 아이템 클래스입니다. 우클릭하면 블럭을 설치하는 기능을 구현하고 있으며, 기타 여러 가지 일도 해 줍니다.

블럭 인스턴스 자체는 아이템이 아니어서, ItemBlock을 생성해서 넣어 주어야 비로소 아이템 형태의 블럭을 얻을 수 있습니다. 만약 ItemBlock을 생성해서 넣어 주지 않는다면 그 블럭은 아이템을 얻을 수 없게 됩니다.

+

ItemBlock도 Item의 자녀 클래스입니다. 그리고 Item에서 필수적으로 행해야 하는 사항들 또한 그대로 존재합니다. 그런데 Registry Name만 지정해 줘도 되나요?



사실, ItemBlock은 인자로 준 Block 인스턴스에서 많은 것을 참조합니다. 그 예로 아이템의 이름, 크리모드 탭이 있겠습니다.

따라서 꼬리에 꼬리를 무는 뱀같은 코드를 작성하지 않아도 ItemBlock을 생성할 수 있습니다.


또한 몇 가지 더 참조되는 사항이 있습니다만, 이 사항들은 Item과 Block을 다시 강좌할 때 알아보도록 합시다.


이제 런쳐를 실행해서 block_first 블럭을 설치해 봅시다. 가관이군요. 아이템과 비슷하게 모델을 안 지정해 줘서 기본값인 자주검정 텍스쳐에 박스를 그린 겁니다만, 나중에 고칩시다. 아무튼 블럭이 나왔다는 점에서 기뻐해도 되는 부분 아니겠습니까?? ???


이제 런쳐를 끄고, 두 번째 블럭을 만듭시다. 블럭은 아이템과 비슷하게 마인크래프트 모드를 만들 때 가장 많이 바리에이션을 만들게 되는 클래스 중 하나이기 때문에, 잘 정리해 둘 필요가 있습니다. 패키지부터 만들어 주세요.


그리고 패키지 안에 BlockSecond라는 이름의 클래스를 만들어 주세요.


약간 코드를 짜 본 모습입니다.

NOTE 1 - 블럭이므로 당연히 Block을 상속해야 합니다. 안할시곰보

NOTE 2 - 생성자에는 블럭의 초기화 과정을 그대로 행하시면 됩니다.

NOTE 3 - 이 메소드는 블럭이 우클릭되었을 때 터집니다. 쉬프트를 눌렀을 때를 제외하고 말이죠.

인자가 오지게 많긴 합니다만, 중요한 건 몇 안 됩니다.

1 World - 블럭이 존재하는 월드입니다. 오버월드에서 클릭되었으면 오버월드고, 지옥에서 클릭되었으면 지옥이고.

2 BlockPos - BlockPos는 숫자 3개로 이루어졌으며, 블럭의 위치를 담고 있습니다. 즉 클릭된 블럭의 위치입니다.

3 IBlockState - 블럭스테이트는 지금은 설명하기 약간 어렵습니다만, 대충 말해 블럭과 메타데이터를 합친 블럭 정보 집대성 인스턴스입니다.

4 EntityPlayer - 이 블럭을 클릭한 플레이어 엔티티입니다.

5 EnumHand - 어느 쪽 손으로 우클릭했는지에 대한 값입니다. Main Hand(오른손)와 Off Hand(왼손) 둘 중 하나이며, 값을 오른손으로 해서 호출했다가 특별한 일이 없을 시 값을 왼손으로 바꿔서 다시 호출합니다. 즉 따로 처리를 안 해 주면 이 메소드는 두 번 호출됩니다.

6 EnumFacing - 커서가 클릭된 블럭의 면입니다. 위쪽을 클릭했으면 Up. 아래쪽을 클릭했으면 Down. 이하동문

7 8 9 float - 각각 커서가 클릭된 x 좌표, y 좌표, z 좌표. 써먹을 데는 거의 없을 겁니다.


NOTE 4 - ItemSecond에서처럼, 이 메소드도 클라이언트에서 따라 호출합니다. 그러니 world#isRemote로 검사를 확실히 해 줘야 합니다.

NOTE 5 - true를 반환하면 해당 블럭 클릭에 관련된 상호작용 처리를 중단합니다.

예를 들어 화로를 클릭하면 손에 든 횃불이 설치되지 않죠. 횃불이 클릭 이벤트를 처리하기 전에 화로가 해당 메소드에서 true를 반환했기 때문입니다.

여기에서도 화로처럼 바로 true를 반환해서, 오른손 왼손 두 쪽에서 모두 메소드를 호출하지 않고 한 번만 호출 후 중단하도록 만들었습니다.


Contents로 돌아가서 BlockSecond도 인스턴스를 생성해 주시고,


BlockFirst와 같이 등재를 해 줍시다.


잘(?) 나옵니다.

이제 모든 아이템과 블럭을 만들었으니, 제대로 된 이름도 지어 주고 모델까지 입혀 봅시다!



3. 프록시


..그 전에, 만들어야 하는 중요한 클래스가 있습니다. 프록시라는 이름의 뭔가 복잡해 보이는 클래스입니다만, 사실 전혀 복잡하지 않습니다.


마인크래프트 코드를 보면 @SideOnly [ net.minecraftforge.fml.relauncher.SideOnly ] 라는 어노테이션을 심심찮게 보실 수 있습니다. 이 녀석이 말하는 사이드가 뭐냐면.. 클라이언트Dedicated 서버 중 어느 사이드인지에 대한 정보입니다. 그리고 사이드 온리란 말은 한쪽 사이드에만 존재한다는 의미입니다.

이런 사이드 온리 옵션이 붙은 것들은 생각보다 많습니다. 서버에서 존재할 필요가 없는 것들은 거의 다 클라이언트 온리입니다. 아이템에 커서를 대면 나오는 설명들, 모델과 타일엔티티 렌더러 등등. 이런 것들은 서버에서 신경 쓸 필요가 없죠.

해당 어노테이션이 붙은 클래스, 메소드, 혹은 변수의 경우, 지금의 해당되는 사이드와 다른 사이드에서 로드할 때 해당 어노테이션이 붙은 곳을 완전히 날려 버립니다. 이렇게 무참히 분쇄당한 곳을 함부로 참조할 경우, 프로그램은 바로 에러를 일으키고 꺼집니다. 뭣같죠. 날려버릴 거면 말이라도 하던가!

..그래도, 크래시를 일으키지 않고 해당 기능을 사용할 수 있는 방법이 있습니다. 이것이 바로 프록시입니다.


프록시의 작동 원리는 이렇습니다. 서버 프록시(혹은 커먼 프록시)와 이를 상속하는 클라이언트 프록시, 총 두 개의 프록시 클래스가 있습니다. 포지가 모드를 로드할 때 Dedicated 서버서버 프록시를, 클라이언트클라이언트 프록시를 자동으로 생성해서 모드 클래스에 넣어줍니다.


이 다음부터 꽤 재미있습니다. 서버 프록시에 메소드를, 예를 들어 모델을 지정해 주는 메소드를 만들고, 아무 것도 하지 않습니다. 클라이언트 프록시에서는 이 메소드를 상속해서 실제 모델을 지정하는 일을 수행하게 합니다.

나중에 모델을 만들어야 할 시점에 해당 메소드를 호출하면, Dedicated 서버가 가진 서버 프록시에서는 아무 일도 일어나지 않습니다. 반면 클라이언트가 가진 클라이언트 프록시에서는 모델을 지정합니다. 클라이언트 프록시가 있어야만 모델을 지정하기에, 결론적으로 서버에서 존재하지 않는 클래스를 참조하는 일 없이 모델을 지정할 수 있습니다.

참 쉽죠?? 걱정 마세요. 안 쉬워도 프록시를 쓰다 보면 쉬워집니다. 아마도요.


모드의 메인 패키지에 CommonProxy라는 이름의 클래스를 만듭니다. 이 클래스가 서버에서 생성되는 커먼 프록시가 됩니다.

+

프록시를 따로 패키지를 만들어서 분류하는 모더들도 있습니다. 자기 취향이니 알아서 선택하시면 됩니다. 이런 분들은 프록시의 패키지명으로 주로 [메인 패키지].proxy의 형태를 쓰는 것 같습니다.


내용물은 매우 저렴합니다. 쓸 메소드는 나중에 추가하면 됩니다.


또 모드의 메인 패키지(혹은 프록시 패키지)에 ClientProxy라는 이름의 클래스를 만듭니다.


저렴하게 CommonProxy만을 상속시켜 주면 됩니다.


그리고 CommonProxy의 필드를 모드 클래스에 만듭니다.

이 @SidedProxy [ net.minecraftforge.fml.common.SidedProxy ] 어노테이션은 모드 인스턴스가 만들어질 때 자동으로 프록시의 클래스를 찾아서 인자가 없는 생성자를 호출해 인스턴스를 생성해 넣어 줍니다.

넣어주는 값은 다음과 같습니다.

clientSide - 문자열 형태로 Client Proxy의 클래스 이름을 패키지명까지 포함해서 적으시면 됩니다.제 경우에는 이름이 ClientProxy이고 패키지가 com.tictim.example이니 com.tictim.example.ClientProxy가 되겠습니다.

serverSide - 문자열 형태로 Common Proxy의 클래스 이름을 패키지명까지 포함해서 적으시면 됩니다. 클라이언트 프록시와 동일한 방법으로 적으시면 됩니다.

+

Q1. 클래스 이름이 틀리면 어떻게 되나요?

A1. 터집니다.

Q2. 인자가 없는 생성자를 호출한다고 했는데, 프록시가 인자가 없는 생성자를 가지고 있지 않을 시 어떻게 되나요?

A2. 터집니다. 또 생성자를 public으로 내놓지 않아도 터집니다. 접근성에 관련된 처리를 하지 않아서 호출이 불가능하기 때문입니다.


놀랍게도 이제 프록시를 다 만들었습니다. 대단해 보이는 이름에 비하면 별로 복잡하지 않았죠?

이제 모델을 등록하러 가 봅시다.


커먼 프록시에 Item을 인자로 받는 메소드를 만들었습니다. 커먼 프록시 자체에서는 아무 일도 하지 않지만, 클라이언트 프록시에서 이 메소드를 오버라이드하여 모델을 등록할 겁니다.


클라이언트 프록시에서 오버라이드된 메소드의 모습입니다.

ModelLoader [ net.minecraftforge.client.model.ModelLoader ] 는 이름에서 알 수 있듯이 아이템과 블럭의 모델을 로드하고 관리하는 클래스입니다. 이 클래스의 setCustomModelResourceLocation(...) 메소드는 해당 아이템의 모델 위치를 지정하는데요. 다음과 같은 인자를 가집니다.

1 Item -  지정할 아이템입니다.

2 int - 아이템의 대미지값을 받습니다. 석탄과 목탄 같이 한 아이템을 공유하지만 대미지값에 따라 텍스쳐가 달라지는 아이템을 보신 적이 있으실 겁니다. 이 값을 바꿔 호출해서 대미지값마다 다른 모델을 부여할 수 있습니다.

다만 지금 우리가 만든 아이템은 그런 기능을 가지고 있지 않으니 딱히 이 값을 만질 필요는 없습니다. 기본값인 0으로 넣어 줍시다.

3 ModelResourceLocation - ModelResourceLocation [ net.minecraft.client.renderer.block.model.ModelResourceLocation ] 은 마인크래프트 json 모델의 위치를 나타내 줍니다. 생성자로 받는 인자는 ResourceLocation과 모델의 바리에이션?을 설명해 주는 String입니다.

여기에서는 아이템의 이름을 적당히 참조해서 모델을 찾도록 ResourceLocation은 아이템의 이름을 넣었고, 모델의 바리에이션은 inventory로 넣었습니다.

+

그런데 ResourceLocation이 뭐죠?

ResourceLocation [ net.minecraft.util.ResourceLocation ] 은 도메인과 패스 두 가지의 문자열을 묶어서 저장하는 클래스입니다. (도메인):(패스)의 형태로 변환됩니다. 마인크래프트에서 F3+H(아마도)를 누른 상태로 아이템에 커서를 가져다 대면 맨 아래에 콜론으로 나뉜 두 개의 단어가 보일 것입니다. minecraft:stone과 같은 것들 말이죠. 이게 바로 ResourceLocation입니다.

ResourceLocation은 이름 그대로 텍스쳐, 모델 등의 리소스Resource경로Location를 얻는 데 사용될 뿐만 아니라, 마인크래프트에 등재되는 모든 아이템과 블럭에게 고유한 키 값을 부여하는 데도 사용됩니다. 우리가 이전에 아이템과 블럭에서 호출한 setRegistryName(...)도 사실 (모드 ID):(인자로 전달한 문자열) 형태의 키 값을 부여하기 위해 호출한 겁니다.

1.11 이후부터는 ResourceLocation의 도메인과 패스에 포함되는 대문자가 모두 소문자로 변환이 되어 버립니다. 따라서 여러분이 1.11~12, 혹은 그 이상의 버전 포팅에 있어서 골머리를 썩히고 싶지 않으시다면 도메인(모드 ID)와 패스(블럭, 아이템 등의 이름)는 소문자만으로 지정해 주시는 게 좋습니다. 저처럼 1.10에 대문자 썼다가 낭패를 보는 일이 없으시길 바랍니다. 흑흑


이제 프록시의 메소드를 사용하여 모델을 지정하면 됩니다. 결과물에 비해선 설명이 상당히 장황하군요. 흠흠

이제 모델의 위치를 지정했으니, 모델 자체를 만들러 가 봅시다.



4. 모델

이 파트에서 설명하는 대상은 1.7 버전에는 없습니다. 1.7에서는 대신 IIcon 등등의 인스턴스를 이용해서 블럭과 아이템 등등을 직접 그리는데, 이에 대해서는 나중에 기회가 되면 설명드리겠습니다. 여기서는 1.8 이후의 모델만을 간단히 강좌합니다.


1.8 버전 때, 마인크래프트의 렌더링 시스템은 엄청난 변화를 겪었습니다. 바로 악명 높은 JSON 모델의 등장입니다. JSON은 간단한 데이터 상수를 기술하는 쉬운 포맷입니다. 마인크래프트는 Pre-Init과 Init 스테이지 사이에서 게임에 등재된 모든 모델들을 읽어들이고 미리 만들어진 모델 렌더러로 변환시킵니다.


4-1. 아이템의 모델


먼저 특정 경로에 폴더를 만들어야 합니다. MDK폴더로 가서 다음 경로까지 폴더를 만들어 주세요. 여기가 마인크래프트가 아이템의 모델을 참조하는 경로가 됩니다.


[MDK 폴더 이름] -> src -> main -> resources -> assets -> [모드 ID] -> models -> item


이제 Item_First의 모델을 만들어 봅시다. 당연히 JSON으로 쓰여져 있으며 내용물은 다음과 같습니다.

2번째 줄 - parent는 다른 모델의 서식을 그대로 베껴 오는 역할을 합니다. 값은 ResourceLocation으로 지정이 되는데요, 이 경우에는 도메인이 없고 패스만 존재하기 때문에 도메인은 기본값인 minecraft, 즉 마인크래프트 바닐라의 것으로 설정이 됩니다.

여기 보이는 minecraft:item/generated라는 위치에 존재하는 json 모델의 서식을 베껴오는데요, 이 모델은 간단히 말하자면 그냥 평범한 아이템입니다.

3번째 줄~5번째 줄 - textures에서는 위에서 불러온 generated로 무슨 텍스쳐들을 렌더링할 것인지를 ResourceLocation으로 전달합니다.

보통 layer0으로 단 한 개의 텍스쳐를 그리도록 명령하며, 여기서는 example:items/item_first라는 이름의 텍스쳐를 찾도록 지정했습니다.


이 json 모델을 방금 만들어 놓은 모델 파일에 .json 확장자를 붙여 저장해 주세요. 이름은 아이템의 setRegistryName에 넣은 그대로 붙여 주시면 됩니다. 저는 item_first를 사용했으니 item_first.json으로 저장해야겠죠?


텍스쳐를 지정했으니, 이제 텍스쳐를 넣어 줘야 합니다. 마인크래프트가 json 모델에서 지정된 ResourceLocation에서 텍스쳐를 찾는 방법은 다음과 같습니다.

(도메인):(패스)  =  assets -> (도메인) -> textures -> (패스).png

여기서 저는 example:items/item_first라는 이름의 텍스쳐를 찾도록 지정했습니다. 따라서 제가 텍스쳐를 넣어야 할 곳은

assets -> example -> textures -> items -> item_first.png

가 됩니다.

디렉토리를 입력하는 것처럼 빗금으로 세부 폴더를 지정할 수 있습니다. 여기서는 items라는 세부 폴더에 텍스쳐를 지정했죠.


1분도 안 돼서 걸작이 나왔습니다. 와!안두인!가면라이더! 정말 멋잇ㅆ씁니다. 모나리자에 비벼 볼 만한 완성도입니다.

다들 그렇게 생각하죠? 어서 그렇다고 말하십시오


아무튼 텍스쳐를 넣어 줍니다. 이걸로 1번째 아이템이 완성되었습니다.


같은 식으로 item_second도 마무리해 줍시다! 이건 혼자서 한 번 해 보세요. 직접 해 보는 것도 많은 도움이 됩니다.


+

json 모델에 오타가 있으셨나요?

그렇다면 F3+T를 입력해 보세요. F3+T는 마인크래프트에서 로딩한 모든 리소스를 다시 로드합니다. 이는 텍스쳐, 모델, lang 파일 등등을 포함합니다. 인게임에서 누르시면 됩니다.


4-2. 블럭의 모델


아이템이 비교적 만들기 쉬웠던 반면, 블럭의 모델은 조금 복잡합니다. 블럭스테이트가 개입하기 때문입니다.


블럭스테이트는 앞에서 간단히 말해서 블럭+메타데이터라고 말씀드렸습니다. 그리고 모델을 렌더링할 때도 블럭스테이트를 참조하는데요, 이에 따라 블럭스테이트의 모든 바리에이션마다 json 모델을 지정할 필요가 있습니다.

하지만 다행히도 우리가 만든 블럭은 바리에이션이 없는 단순한 블럭이기 때문에, 쉽게 모델을 지정할 수 있습니다.


블럭스테이트에 따른 모델을 지정하는 json입니다. 우리는 바리에이션이 없기 때문에 4열에 있는 example:block_first라는 모델만 만들어 주면 됩니다.


이 블럭스테이트 json 파일을 해당 위치에 저장해 주세요.

assets -> [모드 ID] -> blockstates

여기서 마인크래프트가 블럭의 Registry Name과 동일한 이름을 가진 json 파일을 참조합니다.


이번에는 블럭의 모델입니다.

minecraft:block/cube_all은 모든 면이 한 텍스쳐로 감싸져 있는 블럭입니다. textures로 전달한 all 텍스쳐를 받아서 6면과 파티클을 렌더링합니다.


이 블럭 모델은 models -> block에 저장해 주세요. 블럭스테이트에서 모델을 참조할 때 models/block 폴더에서 모델을 찾기 때문입니다.


블럭의 모델만으로는 아이템을 렌더링할 수 없기에 아이템 버전의 블럭에도 모델을 만들어 줘야 합니다. 여기서 우리는 블럭의 모델을 parent로 지정하겠습니다. 딱히 인벤토리 안의 블럭과 월드에 설치된 블럭이 다를 필요도 없으니 말이죠.

만약 아이템과 블럭이 다르게 보이는 것을 원하신다면, 아이템 모델을 구현하던 것처럼 parent를 item/generated로 설정하고 텍스쳐를 넣어 주세요. 깔때기 비슷한 모양새를 만드실 수 있습니다.


아이템의 렌더링에 사용될 모델이니, item 디렉토리에 넣어줍시다.


이번엔 10초도 안 걸려서 만들었습니다. 네, 귀찮습니다. 어차피 제대로 된 모드도 아니고 예제인데 뭐!빼애액!

여러분은 이런 틱팀을 본받지 말고 열심히 도트를 찍어 보도록 하세요.


이번엔 텍스쳐를 assets -> example -> textures -> blocks -> block_first.png에 넣도록 합시다. 블럭 모델에서 그렇게 지정했기 때문입니다. 원하신다면 바꾸셔도 무방합니다.


만들어야 하는 json 파일의 양이 늘어났고 귀찮음도 제곱으로 늘어난 거 같긴 하지만, 두 번째 블럭도 만들어 보도록 합시다!


결과물입니다. 너무 아름답지 않ㅅ습니까ㅣ??

이번엔 아니라고 말씀하셔도 됩니다. 하지만 그렇다고 말해 주시는 것만으로도 저에게는 큰 힘이 될 수도 있고 아닐 수도 있습니다. 자세한 사항은 그렇다는 말씀을 받은 이후 알려드리도록 하겟습니다. 제가 틱팀입니까 갑팀입니까!!앺X아바타입니까!!중얼,,중얼,,



5. 현지화Localization


제대로 아이템이 렌더링되어도 아직 해결되지 않은 사항이 한 가지 있습니다. 그것은 바로...

이름입니다. 이번엔 이 테러블한 이름을 고쳐서 우리에게 친숙한 이름으로 바꿔 봅시다. 바로 lang 파일을 만들어서 말이죠.


lang 파일은 별 거 없습니다. 현지화 전 이름과 현지화 후 이름을 (이전)=(이후) 식으로 대응해 한 줄 한 줄 나열해 놓은 게 다입니다. 마인크래프트에서는 이 lang 파일을 읽어서 우리에게 보이는 이 이상한 item.뭐시기 뭐시기.name 비슷한 이름을 다른 친숙한 이름으로 자동으로 바꿔 줍니다.


이렇게 전에 보이던 이상한 이름들과 이를 대체할 이름을 =으로 대응시킨 파일을 작성해서


ko_kr.lang으로 저장해 주세요. 소문자 맞춰 주시구요.

마인크래프트에서는 한국어 현지화를 할 때 이 ko_kr.lang 파일을 읽어서 사용합니다.


en_us.lang이라는 이름으로도 파일을 만들어 주세요.

이는 한국어 lang 파일보다 중요합니다. 그 이유는 한국어 이외의 현지화를 할 때 다른 lang 파일이 없으면 기본적으로 en_us.lang 즉 영어의 현지화 결과를 출력하기에, en_us.lang이 없으면 한국어에서만 이름이 나오고 다른 나라 말로 바꾸면 이상한 item.뭐시기 뭐시기가 또 출력되는 현상이 생기게 됩니다.

아무리 영어를 못 해도 en_us.lang 파일은 만들어 줍시다. 그 전에 기본적인 단어만 알면 이름 정도는 다 적을 수 있을 겁니다.


이러면 이름에 모델에 기능까지 전부 만드셨습니다. 여기까지 따라오신 분들 모두 수고하셨습니다. 중간에 막히신 분들도 열심히 노력해서 좋은 성과 얻으시길 빕니다.


+

lang 파일에 오타가 있으셨나요?

그렇다면 F3+T를 입력해 보세요. F3+T는 마인크래프트에서 로딩한 모든 리소스를 다시 로드합니다. 이는 텍스쳐, 모델, lang 파일 등등을 포함합니다. 인게임에서 누르시면 됩니다.

복사,,붙여넣기,,앗,,아앗,,


+

우리 한국어가 좀 아픈 것 같아요

한국어가 이상하게 깨지는 이유는 인코딩 때문입니다. ko_kr.lang파일을 열어서 인코딩을 UTF-8로 변환해 주세요.

변환을 못 하시는 분들께서는,,,,,음,,,,, 여기는 메모장 혹은 노트패드++ 강좌가 아니기에, 직접,,,,,


아뇨 어렵지는 않아요. 그냥 쓰기 귀찮아요. 빼애액!!



6. 차회?


다음 화에서....적을 게 약간 애매하기도 하고, 다른 강좌들처럼 바로 타일엔티티+인벤토리 -> GUI로 넘어가는 심플한 과정이 재미없을 수도 있는지라 댓글로 차회에 무엇을 쓸지를 조사해 보고 싶습니다.


1) 초보자가 따라하기 쉬운 절차적 구성 (이 강좌와 같은 구성)

아무것도 바탕에 깔리지 않은 상태에서 읽기 좋습니다. 따라하기는 쉽지만 수박 겉핥기 수준의 글이라서 그 이상의 레벨에서는 얻을 건 별로 없을 겁니다.

커스텀 화로(?) 제작 (타일엔티티, 인벤토리와 컨테이너, GUI)

커스텀 활/포션 제작 (심도 있는 아이템 강좌, 플레이어 인벤토리의 사용법, 포션 효과)

등등.


2) 심도 있는 하나의 클래스에 대한 고찰

하나의 클래스에 대해 집중적으로 서술합니다. 배경 지식이 필요하지만, 미처 알지 못했던 사항들을 발견할지도 모릅니다. 또한 분량이 이런 큰 강좌보다는 짧게 여러 번 나오기에 틱팀이 글을 더 잘 쓴다는 이점도 있습니다(...)

개인적으로는 이런 종류들을 쓰고 싶네요.

아이템(+IItemColor)

블럭(+블럭스테이트)

모델(+Json 모델)

NBT Data(Compound, List, Primitive...)

등등.


사실 둘 다 쓰면 좋기는 합니다. 하지만 제가 맨날 글만 싸지르는 기계도 아니고 그렇게 빠르게 많은 분량의 글을 쓸 수는 없잖아요?? 라고 변명 좀 해 보겠습니다. 하!하!

그럼 이만 변명하는 기계 틱팀은 변명을 하러 물러가겠습니다.안녕여러분





공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]



Posted by Tictim indie.

Q. TTMP Lite 근황은 죽었나요?

A. 님들이 댓글을 안 써서 죽었음.


Tictim과 함께하는 마인크래프트 모딩 101

1. Forge Gradle과 기본 세팅


※ 이 강좌는 1.10 ~ 1.11버전을 기준으로 작성됩니다.


틱팀입니다. 다시 만나 반갑습니다. 처음 보신 분들은 처음 뵙겠습니다. 틱팀입니다.


정말 오랜 시간이 지나고 나서야 모딩 강좌를 쓰게 되었습니다. 사실 처음부터 모딩 강좌를 쓰고 싶었습니다. 멋지잖아요. 어그로도 잘 끌리고

아무튼, 이 모딩 강좌 시리즈로 어그로를 끌어 블로그를 되살ㄹ모딩을 배우고 싶은 많은 분들에게 여러 정보를 드리고 싶습니다.


시작하기 전에, 이 강좌에 관한 몇 가지 사항들을 말씀드리고 싶습니다. 숙지해 주세요.


1. 만약 Java를 배우지 않았다면, 먼저 Java를 배우십시오.

이 모딩 강좌 시리즈는 전반적으로 Java에 대한 이해를 필요로 합니다. 모드 메이커(웃음) 비슷한 것들은 거릅니다.

하지만 Java를 배워라! 해서 막막해하실 필요는 없습니다. 저는 Java는 제대로 된 입문서 한 권(정석이나 뭐 이런 것)과 꾸준히 책을 따라해보는 마음가짐만 있으면 못 배울 게 절대 아니라고 봅니다. 인터넷에 올라온 강좌들은.. 저는 뭔가 보기가 불편하더군요. 잘 찾아보면 좋은 것들도 있겠지만 저는 책 한 권으로 따라해보면서 배웠습니다. 책을 다 읽어도 모르겠으면 아예 책을 끼고 살면서 모르는 것을 그때그때 찾아서 따라 해보시면 될 겁니다.

인터넷 강좌를 보시던, 책을 보시던, 중요한 건 꾸준함입니다.


2. 댓글에 달린 질문은 답변해 드립니다. 하지만 소스코드는 Pastebin을 사용해서 보내 주셔야 합니다.

아무런 하이라이트도 없이 드르르륵 늘어진 코드만큼 보기 싫은 코드도 없습니다. Pastebin은 최소한의 예의라고 생각해 주세요.

또, 답변에 구문 오류입니다라는 말이 있으면, Java 자체의 문법을 잘못 지켰다는 소리입니다. 그리고 이는 곧 틱팀이 문제를 고쳐 주지 않으니 여러분이 찾아서 해결해야 한다는 뜻입니다.


3. 강좌에 사용된 소스코드의 Copy/Paste는 지원하지 않을 예정입니다.

Java를 배우는 제대로 된 방법은 직접 타이핑해 보고 빌드해 보고 실험해 보는 것입니다. 소스코드에 대한 이해와 경험도 없이 Ctrl+C Ctrl+V로 강좌를 마무리해 버리면 기억에도 안 남고 나중에 써먹지도 못합니다.


서문이 너무 길어졌습니다. 시작하죠.


0. Java 세팅


일단, Java를 배우셨다면 설치되었을 JDK환경 변수 세팅은 여기서도 사용합니다. 혹시나 모르시는 분들은 여기에서 설명하기엔 조금 긴 부분이니 구글 하시면 됩니다. 간단하게 말씀드리자면


http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

1. JDK 설치.


https://www.google.com/search?q=jdk+%ED%99%98%EA%B2%BD+%EB%B3%80%EC%88%98+%EC%84%A4%EC%A0%95&oq=jdk+%ED%99%98%EA%B2%BD+%EB%B3%80%EC%88%98+%EC%84%A4%EC%A0%95&aqs=chrome..69i57j0l5.5351j0j9&sourceid=chrome&ie=UTF-8

2. 환경 변수 세팅.


https://eclipse.org/home/index.php

3. 그리고 이클립스 설치.



1. Forge Gradle


포지팀에서는 마인크래프트 코드를 디컴파일해 주고, 그 와중에 버그도 고쳐주고(..), 유용한 클래스도 추가해 주고...해서 유저들이 더 쉽게 마인크래프트를 입맛대로 고칠 수 있게 해 줍니다. 또 마인크래프트 모드를 쉽게 빌드할 수 있는 툴을 배포하는데요, 우리는 이것을 받아서 개발 환경을 만들 겁니다.


http://www.minecraftforge.net/forum/

마인크래프트 포지의 공식 사이트입니다. 여기서 릴리즈된 마인크래프트 포지의 파일을 받거나, 여러 정보를 얻을 수도 있습니다. 영어를 할 줄 안다면 포럼에 질문도 할 수 있겠죠.


일단, 맨 위에 Home Files Docs의 3개 화면을 보실 수 있겠습니다. Home은 당신이 보고 계시는 바로 그 곳이며, Files는 포지 파일을 받을 수 있는 곳입니다. Docs는 포지 모드 개발에 매우 도움이 되는 기본적인 사항들이 영문으로 적혀 있습니다. 걱정 마세요, 제가 다 설명해 드릴 예정입니다.

여기서 우리는 Files로 가시면 됩니다.


개발하려는 마인크래프트 버전을 골라서 최신(혹은 추천하는) 버전의 Mdk라고 되어 있는 것을 내려받습니다. 1.7 이하에서는 Src가 그것입니다. 이 강좌는 1.11을 기준으로 작성될 예정이기에, 저는 1.11 버전의 Mdk를 받았습니다.


해당 파일을 받아서 압축을 해제하시면 됩니다. 보기 좋게 이름도 바꿔 주시구요.

안에는 빌드/라이브러리 관리 전용 툴인 Gradle의 구성요소들과 편리한 Github 연동을 위한 .gitignore 파일, IDK인 이클립스와의 빠른 연동을 위한 eclipse 폴더, 그리고 여러분의 모드에 들어갈 것들을 집어넣는 폴더인 src 폴더가 있습니다. 그 이외에는 크레딧과 라이센스 명시를 위한 텍스트 파일, 체인지로그, 간단한 사용설명서(..)가 있습니다.

먼저 우리는 지금 보고 있는 mdk 폴더에서 cmd를 호출할 겁니다. Shift를 누른 상태로 빈 곳을 클릭한 후 여기서 명령 창 열기를 선택하세요.


cmd 창입니다. gradlew setupDecompWorkspace eclipse를 입력하세요. 맨 앞의 gradlew는 gradlew.bat을 실행한다는 의미이고, setupDecompWorkspace는 포지 모드의 개발 환경을 구축하라는 소리고, eclipse는 eclipse 폴더를 해당 프로젝트의 설정에 맞게 초기화시키라는 소리입니다.

이 작업은 꽤 많은 시간을 잡아먹으니 켜 두시고 할 일 하고 계세요. 끝나면 완료되었다는 콘솔 창의 메시지와 함께 mdk 파일이 늘어나 있을 겁니다.


그리고 eclipse에 [mdk 폴더]/eclipse를 Workspace로 지정하여 프로젝트를 열어서 왼쪽 화면에 있는 패키지 익스플로러에 mdk 안의 파일이 보이면 환경 세팅은 끝난 겁니다.

아, src/main/java 항목 아래에 있는 패키지와 클래스는 지워 버려도 무방합니다. 포지에서 주는 예제 클래스이고, 별 다른 건 없습니다. 이 강좌 한 장 안에서 다 설명하는 내용입니다. 지금 지우지 않아도, 빌드할 때는 반드시 지우셔야 합니다.



2. 모드 클래스 작성


모든 포지 모드들은 모드 클래스를 가지고 있습니다. 모드 클래스는 모드 ID, 모드의 이름 등 모드에 관한 정보를 가지고 있으며 FML에서 터트려 주는 이벤트를 받아서 아이템과 블럭 등등을 게임에 등록하는 일을 맡습니다.


먼저 모드의 이름을 기반으로 패키지를 만들어 봅시다. 정리하는 일은 세상에서 가장 중요하니까요. src/main/java를 우클릭 -> New -> Package 클릭.

패키지 이름은 아무거나 붙여서 만들 수도 있지만, 제가 추천드리는 방법은 이 둘 중 하나입니다.


(도메인 이름) . (팀 혹은 제작자 이름) . (프로젝트 이름) . [세부 패키지]

혹은 (팀 혹은 제작자 이름) . (프로젝트 이름) . [세부 패키지]

여기서 프로젝트 이름은 여러분 모드의 ID를 붙이면 됩니다.

제 모드의 경우, 도메인은 아무거나 붙여서(...) com으로 지었고, 제작자는 tictim을 붙였습니다. 따라서

com.tictim.ttmpcore

com.tictim.hungerkeeper

com.tictim.mobcapabilities

등등의 패키지 이름이 됩니다.

+

참고할 만한 사항으로, 1999년에 Sun에서 패키지, 클래스, 함수 등등의 이름 제정에 관한 규칙에 대해 기술한 아티클이 있습니다.만, 영어입니다.

http://www.oracle.com/technetwork/java/codeconventions-135099.html


어쨌든, 저는 간단하게 com.tictim.example로 할게요. 여러분은 마음에 드시는 걸로 만드시면 됩니다.


패키지 다음엔.. 패키지 안에 모드 클래스를 만듭시다. 방금 만든 패키지를 우클릭 -> New -> Class 클릭.

보통 모드 클래스의 이름은 모드의 이름으로 짓습니다. 물론 클래스 작명의 일반적인 규칙대로 맨 첫 번째 글자를 대문자로 해서 말이죠. 가끔 뒤에 Mod를 붙이기도 합니다. 저만 쓰는 것 같습니다만. 흠흠.

아무튼 모드 이름이 Apple이라면 모드 클래스 이름은 Apple, 혹은 AppleMod. 모드 이름이 Ball이라면 모드 클래스 이름은 Ball, 혹은 BallMod. 이런 식으로 지으시면 됩니다.


그리고, 클래스에 @Mod [ net.minecraftforge.fml.common.Mod ] 어노테이션을 붙입니다. 이 어노테이션이 붙어 있는 클래스는 마인크래프트가 시작될 때 포지가 다 긁어모아서 모드로 인식해 주며, 자동으로 인스턴스를 만들어 주고 여러 일을 합니다.


이 어노테이션이 받는 인자는 이러합니다.

modid = 모드의 고유한 ID. 다른 모드와 겹치면 꽤나 안 좋은 일이 일어납니다. ResourceLocation같은 오만 가지 사항에 들어갈 일이 많으니, 호환성을 위해 소문자만으로 구성하시는 것이 좋습니다.

name = 모드의 이름. 좀 더 유저에게 친숙한 쪽이죠.

version = 모드의 버전입니다. 포지에서는 숫자 4개로 이루어진 버전 카운팅을 추천합니다. 0.0.0.0, 1.0.3.0 이런 식이죠. 우리는 아직 버전 카운팅을 안 했고 아직 개발 중이기에 초기값인 0.0.0.0으로 맞춰 주시면 됩니다.

+

포지도큐에서 버전 카운팅에 대한 페이지를 찾아볼 수 있습니다.만, 영어입니다.

https://mcforge.readthedocs.io/en/latest/conventions/versioning/


이 밖에도 많은 양의 추가 정보를 줄 수도 있지만 더 설명하면 아주 빠르게 복잡해지니 넘어갑시다.

저 3가지의 정보는 보통 모드 클래스 안에 public static final field의 형태로 선언해 둡니다. 특히 Modid는 말이죠.


그 다음에는 포지의 Loading Stages에 맞춰 메소드를 호출받도록 해 봅시다.

포지가 @Mod 어노테이션이 붙은 클래스를 모드 클래스로 인식을 하듯이, 모드 클래스 안의 메소드에 @EventHandler [ net.minecraftforge.fml.common.Mod.EventHandler ] 어노테이션을 붙임으로써 "내가 이 이벤트가 터질 때 메소드를 호출받고 싶다"라고 FML에게 알려 줄 수 있습니다.

하지만 아무 메소드에다 다 붙여서 효과를 보는 것은 아니고, FML Event 인스턴스 하나를 인자로 받는 메소드만 유효한 이벤트 핸들러로 등록이 가능합니다. 이름은 상관이 없습니다.


포지의 Loading Stages는 크게 3가지로 나뉩니다. 각각 단계별로 해야 하는 작업이 다르니 이 점 명심하세요.

이름

설명

역할(?)

Pre-Initialization

[ net.minecraftforge.fml.common.event.FMLPreInitializationEvent ]

마인크래프트가 블럭과 아이템을 등록하고 모델을 만들기 이전 단계입니다.

ItemColors와 같은 렌더링 관련 인스턴스는 이 단계에서는 생성되지 않았을 수도 있습니다.

블럭/ 아이템 등록

타일엔티티 등록

엔티티 등록

오어딕 등록

 Initialization

net.minecraftforge.fml.common.event.FMLInitializationEvent ]

Pre-Init 이후의 단계입니다. 아이템과 블럭의 등록이 끝나고, 렌더링 관련 인스턴스 또한 생성됩니다.

월드젠 등록

레시피 등록

이벤트 핸들러 등록

IMC 메시지

 Post-Initialization

[ net.minecraftforge.fml.common.event.FMLPostInitializationEvent ]

거의 모든 등록이 끝난 시점입니다. 주로 다른 모드와 관련된 일을 합니다.

모드 호환성 개선

기타 타 모드 관련

+

포지도큐에서 Loading Stages에 대한 페이지를 찾아볼 수 있습니다.만, 영어입니다.

https://mcforge.readthedocs.io/en/latest/conventions/loadstages/

또한 숙련된 모더 분께서는 RegistryEvent에 관한 페이지도 읽어 보시는 것을 추천드립니다.만, 영어입니다.

https://mcforge.readthedocs.io/en/latest/concepts/registries/#registering-things


이 강좌에서는 저 역할을 테스트해 보지는 않고, 간단하게 이벤트를 제대로 받았는지 테스트해 보기로 합시다.

이벤트가 터졌다면 stdout으로 해당 이벤트에 있는 메시지를 남기겠죠?


실행해서 결과를 보고 싶으시다면, 위쪽 칸에 있는 재생 버튼을 클릭하시면 됩니다. Server를 클릭하여 Dedicated Server를 실행하실 수도 있습니다. 하지만 로그인은 할 수 없으니, 온라인 모드는 끄셔야 합니다.


또한, java 코드 작성 창 아래에 있는 콘솔에 로그가 출력됩니다. stdout으로 세 개의 로그가 출력된 게 보이시나요?


다음 시간에는 아이템과 블럭을 만들어 보고, 모델을 간단하게 알아 보도록 하겠심미다. 깊은 내용은 아니니 간단할 거예요. 그럼 여러분 안녕




공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]


Posted by Tictim indie.
카테고리 없음2017. 8. 25. 22:45

무사히 2화가 올라왔습니다. 아직 틱팀은 죽지 않았습니다. 곧 죽을 것 같긴 합니다만.


TTMP Lite v.1 REMASTERED

Episode II

로미오와 철광석


틱팀이 또!..가 아니라, 놀랍게도 틱팀이 다음 화를 썼습니다. 모두 박수로 축하해줍시다. 와!짝짝!

댓글로도 축하해줍시다. 댓글이 안 달리면 매우 외롭고 싸늘하고 비취 수리검이 내 명치에 날아와 2대미지를 주고 2/2 비취 골렘을 소환합니다.


2화의 시작은 테네신의 '테네신 한' 허기 수치로 시작합니다. 정말 멋진 시작입니다. 흠,,,,,,,,,,


닥치고 광질이나 합시다.

솔직히 그렉텍이 들어가 있고 다른 모드의 광물젠이 없는 한 초반에 할 일은 황철광을 빠르게 찾고 철과 구리를 습득한 다음 아무튼 생성된 주석으로 청동기 메타를 맞이하는 것밖에 없습니다. 이게 존나게 운빨 좆망겜이긴 하지만 딱 한 번만 터지면 게임을 쉽게 이끌어갈 수 있기에.. 그래서 한 번만 터지라고 좀!!


그렇게 돌의 바다 속을 헤매는 사이 작은 동굴도 보고


용의 눈으로 던전도 보고


이건 용의 눈이 아니지만(...) 폐광도 찾았습니다.

다들 들어가면 얻어터지니까 못 들어가긴 하지만 상타치 아닙니까!어!어!


하지만 철광석은 나오지 않았다.


톱을 만들었습니다. 그렉텍의 도구인 툴은 너프당한 목재와 막대기 조합법의 교환비를 원래대로 돌려주는 것이나 기타 괴상한 그렉텍만 쓰는 재료를 만드는 것 이외에도, 너프로 만들 수 없게 된 나무 반 블럭을 제작할 수 있게 해 줍니다.

나무 반 블럭은 어디에 써먹냐구요?


벌통을 만드는 데 씁니다.

하지만 바다 위 조약돌 플랫폼 위에서는 꽃을 심을 수가 없는 관계로, 고생해서 만든 벌통은 별로 안 예쁜 장식용 가구가 되어 버렸습니다. 하 하.


그렇습니다. 우리는 하찮은 벌들 따윈 버려두고 진정한 구세주를 찾아 나서야 합니다


첨벙첨벙


그렇게 오벨리스크를 건드려 버린 테 '더 아만보' 네신


전에도 있었던 일 같은데... 사움 오벨리스크에서 노드를 갈구는 피떡갈비 주술사들은 한 번 어그로가 끌리면 개 빡쳐서 때린 놈을 조지러 달려듭니다. 그리고 한번 달려들면 디스폰 대상이 되어 크림슨 파밍을 못 하게 됩니다.


아마도 칭찬입니다.


벌써 월드에 발견된 레톤 광맥이 3개째... 정말 자원이 풍부합니다.


그리고 틱팀이 따끈따끈한 레톤광맥을 하나 더 찾으면서 4개가 되었습니다.


앨빈은 책상 위에서 연구 종이하고 섹스하는 묘수충이지 연금술사가 아닙니다


흠,,인터레스팅,,


일생불 집합소


그렇게 틱팀은 고통 상태가 되고 파티를 조졌다고 합니다. 어 씽귤러 스트라이크!


라고 할 찰나에, 뻗어나갈 새로운 길을 모색하며 땅굴을 걷던 중 찾던 광맥을 발견했습니다.


안 보이신다구요?


중요한 부분만 잘라 드렸습니다

안 보이신다구요? 흠... 보이긴 보이는데 저게 광석이냐구요? 흠.....


제대로 빡친 틱팀


범인은 이타치로 밝혀졌습니다. 어쨌든 게임 끝! 라운드 2 시작!


군중심리가 이렇게 공정합니다


그리고 틱팀은 눈을 조금 쉬게 하러 낮잠을 자러 갔다가 3시간을 자고 돌아왔습니다. 데헷헷


돌아와 보니 지옥문이 이미 뚫려 있었습니다. 한 번 들어가 봅시다.


입☆성

용암 바다 위 스카이블럭이나 출구가 어딘지도 모르는 동굴 같은 곳이 아니라 다행이군요. 용암도 바로 옆에서 뜰 수 있고, 천장도 트여 있고. 나쁘지 않아 보입니다.


으 극혐. 난 저런 거 허용한 적 없는데.

하지만 관심도 없고 캘 수도 없으니 그냥 지나치도록 합시다...


그와중 석영 캐다가 인퍼널 벌집 발견. 내용물은 쓰레기였습니다.


0코 1/1 하이


테네신 식도막 개통...은 아니고, 이번 서버는 식도막이 6겹입니다. 그니까 인생쓴맛 사이클 방지 횟수가 6회란 소리(..)

저 바게뜨로 6번을 다 써버렸는지는 모르지만 김치를 먹어버렸던 것 같기도 하고 아닌 것 같기도 합니다만 어쨌든 식도막이 뚫렸을 수도 있고 아닐 수도 있습니다.


개소리는 됐고 유적이나 털어갑시다


자철광 하이.

자철광은 금광과 거의 내용물이 일치하지만 금 대신 철이 나온다고 보시면 됩니다. 즉 쓰레깁니다.


그렇게 틱팀은 스켈레톤에게 맞아 죽었다.


떨어진 템을 줍기 위해 다시 길을 가는...데...


넌 못 지나간다


그래도 이후 어떻게 똥꼬쇼를 해서 줍고 튀었다고 합니다.


그 사이 테네신은 게임을 터트려버리고


사실 광물 5개짜리 병신광맥이어서 본전도 안뽑혔다고. ㅋㅋ


모노미콘을 만들었습니다. 사움크래프트를 만져야 주석도 안정적으로 생산해낼 수 있고, 사용 가능한 허기가 제한적이기에 한 목숨 당 활동 포텐셜이 제한되어 있는 TTMP의 특성(..)상 여행자의 부츠는 활동 포텐셜을 매우 크게 높여주는 킹갓엠페러 아이템이죠.

아무튼좋음


다음은 먹물을 얻을 차례죠.


이리 와라 이 시커먼 놈


건질 만큼 건졌습니다.


그 와중 '테네신'한 테네신


틱팀의 웨이포인트를 알아보ㅈ.....ㅏ?


그만 알아보자.


리서치 테이블을 만들었습니다. 이제 이 서버도 초반은 넘어갔다고 할 수 있겠...?습니다.

이제 남은 사움 세팅은 사우모미터 뿐이군요. 사우모미터는 제작에 금을 필요로 하는 관계로 금광석에서 몇 개 건져 와야 합니다.


그런데..어디서 일은 안하고 연구만 뒈지라 뚫는 벌레새끼 깨어나는 소리 안 들려요?


하지만 놀랍게도 금광맥을 캔다 해 놓고 곡괭이를 안 가져온 틱팀

틱팀의 테네신화...


잘 가요...내 사랑 골-드..... 뭐 하지만 어때요! 다음 화에 주우러 가면 됩니다!

앞에서도 말씀드렸다시피 댓글이 안 달리면 매우 외롭고 싸늘하고 궁극의 역병이 내 명치에 날아와 피해를 5 주고 카드를 5장 뽑고 방어도를 +5 얻고 5/5 구울을 하나 소환합니다. 

투비컨.



쉐이더를 켜 보았다

뭔가 어설픈 쉐이더


그래도 덜 어설픈데 예쁘진 않은 쉐이더




공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]


Posted by Tictim indie.

그렇습니다. 또 재탕입니다!! 하지만 이 재탕은 다른 재탕과는 다릅니다. 아무튼 다릅니다.


TTMP Lite v.1 REMASTERED

Episode I

사두사미


전 세계에 계신 팬 분들 모두 감사드립니다. 마지막으로 열린 지 도대체 몇 개월이 지났는지 기억도 못 하는 TTMP가 드디어 1.7찐이긴 하지만 어쨌든 서버를 열게 되었습니다.

놀랍게도 코노조 블로그가 얼어뒤질 시기에도 TTMP는 멀쩡히 살아 있었습니다. 엄청나게 엉뚱한 방향으로 살아 있기는 하지만 말입니다... 틱팀도 열심히...? 열심히 1.11 버전에서 모드를 만들고 있죠. 하지만 그건 이 글의 토픽이 아니니 본론으로 돌아갑시다.


TTMP 라이트는 무려 2015년에 제작된 TTMP팩으로, 이상한 모드를 잔뜩 구겨넣어서 플레이했던 다른 시즌과는 달리 최소한의 모드만을 넣고 쉐이더를 켜 보자!라는 취지에서 개발되었던 팩입니다. 또한 굉장히 쉽기도....? 합니다. 제가 2년전 저를 몰라서 이게 어려웠는지 쉬웠는지도 구분이 안 가네요. 흠흠

또한 이 팩은 TTMP 역사상 가장 성공적이었던 팩(...)이었습니다. 그렉텍이 들어온 이후로 TTMP의 역사는 그야말로 참혹했죠. 이런 대학살의 현장 위에서 무려 사움 보이드 테크 최후반을 갈 뻔하고 그렉텍 MV도 갈 뻔한 팩 되겠습니다.

이 REMASTERED 팩에서는 기존의 컨텐츠를 최대한 살리고자 추가적인 강력한 너프는 만들지 않았으며, 기존 모드 리스트는 버전 업데이트를 제외하면 거의 바꾸지 않았습니다.

한 가지 차이점이 있다면 본격 무한자원모드 포레스트리가 합류했다는 점이 있겠습니다. 아무래도 그렉텍과 사움크래프트만 하면 물리는 감이 있고, 포레스트리는 그렉텍의 지랄맞게 긴 삼만리 테크트리와 병행할 만큼 긴 컨텐츠가 완성도 있게 짜여진 모드니까요.


서론이 존나 길군요. 게임이나 합시다. 입장!


..는 오밤중에 입장해서 스샷을 찍을 틈도 없이 땅을 파고 숨어야 했습니다.

지금 보니 서버를 먼저 틀어놓고 있었군요. 껄껄


그리고 척살당하는 다른 인원들

눈치 빠르게 숨지 못한 그들의 잘못입니다.


그리고 이타치의 강인함을 몸소 보여주는 강한 닌자 등장(퇴장)

어...뭔가 불길한데.


잠시 후 해가 뜨고 겨우 활동할 수 있게 되었습니다.


지하벙커 S.E.X의 외관


그리고 족같은 스페셜AI 보정 받은 2미터 거인의 습격


싸우다가 쳐맞아 뒤지고 다시 지하벙커 섹스로 돌아가야 했습니다.


아, 예예.


하지만 바깥에 있던 테네신은 멀쩡하지 못했습니다


설명: 문 닫힌 지하벙커 SEX에 테네신이 들어온 장면


조금 탐사를 나갔습니다. 스폰 지역이 꽤나 큰 섬 지대이기 때문에 해안가도 많고, 사탕수수도 자라고 있더군요.


자기 결정을 기억 못할 뻔 한 틔틘 머튽

이번 시즌 서버에는 인벤세이브 옵션이 없습니다. 이전에는 인벤킵도 켜고 팅커스 허기킵도 켜서 해피스트 자살을 했지만 솔직히 인벤세이브 씹사기잖아요


그리고 집 앞에서 토템도 발견. 오밤중에 진격거를 찍었던 걸 생각하면 스포너 노드(?)인가 보군요.

그나저나 웨일라는 왜 노드 내용물을 스포일러하는 것인가


사탕수수도 찾았으니 이제 필요한 건 석탄입니다. 횃불을 만들기 위해서죠.

2015년작 라이트에서는 횃불 조합법을 막대+종이+목탄으로 너프했습니다. 또한 리마스터에서도 그대로 이어받았죠. 다른 시즌의 철을 쳐먹는 횃불이나 아예 못 만드는(..) 횃불 같은 것에 비하면 양반이다 못해 보살인 셈입니다. 하지만 그렉텍 언오피셜이 최근 업데이트를 강행하면서 종이와 목탄이 너프되었기에(....) 의도하지는 않았지만 초반에는 조금 더 힘들어졌다고 할 수 있겠습니다.


간단하게 그렉텍 언오피셜이 저지른 만행을 살펴보자면, 목탄은 더 이상 화로에서 제작할 수 없습니다. 대신 목탄을 만드는 그렉텍 기계(?)가 따로 있죠. 이 기계는 전기나 스팀은 안 먹고, 기계 밑에 나무 원목을 묻어 놓고 흙으로 감주면 잠시 후 나무 원목들을 캘 수 있는 목탄들로 바꿔줍니다. 연료를 전혀 필요로 하지 않고 행운 도끼로 목탄을 수확할 시 추가적인 교환비를 내니 상당히 후하다 볼 수도 있겠지만, 이 기계는 제작에 청동을 필요로 합니다.

또한 그렉텍의 초반 레시피가 약간 바뀌면서 종이도 그 대상이 되었는데, 예전엔 그냥 사탕수수 -> 종이 교환비가 3:2라도 그냥 늘어다 놓으면 종이가 되던 것을 막자사발로 사탕수수 3개를 갈아서 종이 가루(??)를 2개 만들고 -> 이 종이 가루 3개를 돌 반블럭 2개와 조합해서(돌 반블럭은 소모되지 않습니다.) 종이 2개를 만드는 굉장히 귀찮은 조합법으로 바뀌었습니다. 단순히 교환비가 앰창이 된 것 뿐만 아니라 고작 사탕수수 간 걸로 부서진 모르타르를 다시 만드는 노동과 그렇게 만들어진 모르타르가 온갖 괴상한 이유로 박살나는 걸 지켜보는 것에 대한 스트레스(....)가 늘어난다는 점. 아무튼 씨발련입니다


아무튼 석탄과 철과 구리를 찾으러 아래로 아래로


중간에 동굴도 발견했고


곧 행3 곡괭이가 되어 버릴 물샤드도 발견했고


좀비도 발견....넌 안 봐도 됐는데.


기껏 한 놈 족쳤더니 동료부르기를 시전하시는 비열한 얼라이언스 거인님


결국 광질이고 뭐고 다 팽개치고 빤쓰런이나 했고 틱팀은 서버 시작 30분도 채 안 돼 허기 3을 공중으로 날려 버렸습니다.

아, 물론 TTMP의 필수요소 같은 존재인 인생의 쓴맛은 존재합니다. 조금 이---지하게 만들고자 음식 사이클은 100으로 설정했습니다. 너무 쉽죠? 하하.


그리고 약한 닌자 이타치 재등장


설명충: 쉐이더를 켜면 어째선지 NEI의 X자 밝기 오버레이가 보이지 않게 됩니다


룩딸충 앨빈


하지만 역시 '그'였습니다


처음 잡은 지하벙커가 너무 구진 관계로 새로 터를 잡았습니다. 꽤 오랜만에 물 아래에 집을 지어보기로.

그런데..


위 사진에서 두 명이 동시에 아래로 들어갔다가 나올 수도 없고 아래를 팔 수도 없는 괴상한 사태가 발생한 것


이 와중 솔로몬 틱팀 깜짝 등장!


그는 두 명의 서버원을 킥하고 혼자서 집을 완성했어요



수면 아래까지 파고 내려간 모습. 밤인 관계로 나무를 더 못 캐서 최대한 사다리를 아끼기 위해 벽타기를 하도록 사다리를 놓았습니다. 뭐 어때, 부유해지면 바꾸지.


다시 집결한 세 명의 서버원들


이 와중 팅컨스 조합대를 기억 못하는 테만보

아니 잠깐. 뭐? 틱만보?


역시 테만보는 뭐가 달라도 다릅니다


어쨌든 지금은 광질을 해야 할 때입니다. 그렉텍의 초반은 얼마나 황철광을 빨리 찾냐라고 해도 무방할 정도로 굉장히 황철광맥에 의존도가 높기 때문에 바닐라에서 다이아 찾듯이 미친 듯이 돌의 바다 속을 헤매야 합니다.


그리고 흑연 광맥 발견.

흑연 광맥에는 도대체 어디 써먹는지 기억이 나질 않는 흑연이 발에 차이게 널려 있으며 약간의 석탄과 다이아몬드가 존재합니다.


벌써부터 귀환석 모드(웃음)를 그리워하는 그들


그리고 앨빈은 니켈광을 터트렸습니다.

나중에 보니, 니켈 광맥에서 가끔씩 나오는 코발타이트 광석은 초반에 꽤나 좋은 그렉텍 툴 재료가 되더군요.


횃불도 못 만들고 다른 광원도 없는 그들의 채팅


역시 테만보는 뭐가 달라도 다릅니다


틱팀 그는 채팅으로 에러를 만듭니다


여러분도 따라해보세요. 읍읍!


..사실 진짜 런타임 에러는 아니고, :가 들어간 챗이 잘못된 URL 링크로 인식되었는데 핸들링을 못하고 튕겨 버리는 문제 같습니다. 인디게임 극혐


2미터 거인들 하이


지금까지의 데스 수를 알아봅시다. 오잉?? 웬 일로 틱팀이 가장 많이 죽지 않았습니다.


하지만 사실 테네신의 죽음은 자살이 아니라 쳐맞아 죽은 횟수로 3분의 1이 뻥튀기된 숫자였다고(...)


이타치는 역시 이타치다운 숫자입니다.





이번에 준비한 스샷은 이것이 전부입니다. 다음 화에 봅시다. 아니 볼 수도 있고 못 볼 수도 있습니다. 아니...봅시다.



개발 비화: 쉐이더

구와아아아아악


엘드리치 공무원 여러분들 오늘도 수고 많으십니다


구와아아아아아아아아아아악




공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]


Posted by Tictim indie.


..미안합니다. 정말로. ㄹㅇ루다가. 블로그를 까맣게 잊어버리고 있었습니다.

하지만 아무도 안보잖아 어차피


쓸 필요가 있나



틱팀. 모딩 근-황.


드디어 드디어 새 모드 Tictim's MobCapabilities.. 속칭 틱퍼널(.....)이 알파 테스터가 되었습니다. 사실 한참 전에 된 이후로 업뎃이 없지만, 뭐 어때요.

틱퍼널은 인퍼널 몹과 비슷하게, 몹들에게 여러 가지 능력을 붙여서 어썸하게 몹을 강화합니다. 이외에도 강화된 몹들을 잡아 얻는 아이템으로 여러 가지 무기와 방어구를 만들 수도 있습니다.


각각의 능력들은 COMMON, UNCOMMON, RARE, EPIC의 4가지 티어로 나뉩니다.

모든 종류의 몹들은 스폰될 때 일정한 확률로 특정 티어의 능력들을 몇 개 받게 됩니다. 더 자세한 능력 생성에 관한 것은...나중에 이야기하죠.


또한, 몹들이 드랍하는 아이템을 이용해 전투에 도움을 주는 꽤나 특수하지만 좆사기한 효과를 가지는 아이템들을 만들 수 있습니다. 예를 들면...

드래곤 슬레이어는 공격 속도도 느리고, 손에 들면 이동 속도가 느려지지만 넉백 저항과 방어도를 얻습니다. 하지만 30체력 이상의 적을 공격할 때의 피해는 1.25배가 됩니다.

또한, 이 칼로 뚝배기를 하나 깨 버릴 때마다 30체력 이상의 적 상대로 피해 증가량이 0.0002 증가하여 최대 4배가 됩니다. 열심히 스택을 쌓으면 후반엔 인챈트에 갑옷에 이상한거 다 쳐바르고 내리치면 뚝배기가 사르르 녹아버리는 셈(...).

사실 굳이 안 발라도 스택 다 쌓으면 위더 체력바가 쓰르륵하고 비어 버리는 기적 같은 일이 벌어집니다. 너프해야 하나..? 이거.

또한, 동일한 재료로 만드는 광전사 갑주가 있습니다. 이 갑옷은 입으면 느려지지만(..) 꽤나 높은 방어도를 줍니다.

이 갑옷은 세트 보너스가 있습니다. 바로 드래곤 슬레이어의 "뚝배기" 효과가 30체력 이하의 상대에게도 적용되는 것(..) 판단은 알아서. 전 이게 너무 구데기고 칼이 사기로 보입니다만 어쩌구 저쩌구

다른 종류의 갑옷으로는 테라스톤 갑옷이 있습니다. 이 갑옷은 약간의 방어 강도를 가집니다.

또한 이 갑옷도 세트 보너스가 있습니다. 모든 갑옷 파트를 끼고 대미지를 입으면 3초간 테라스톤 저항 효과를 얻으며, 3초 이내에 받는 추가 피해는 효과를 1중첩 증가시키고 지속 시간을 3초로 다시 갱신합니다.

테라스톤 저항 효과를 가진 상태에서 입은 피해는 중첩 당 10% 감소하여 최대 50%의 피해를 감소시킵니다.


테스터 때 정말로 애미가 없었던 능력 근성(맞을 때마다 3초간 저항 버프 +1. 하나당 20% 딜 감소여서 5에 도달하면 아무런 피해를 입지 않는데다가 메커니즘이 엔티티가 쳐맞음->이벤트 검사->버프 추가->딜 연산이기 때문에 아무것도 없을 때 쳐맞아도 기본 20% 저항을 받게 됩니다. 즉 20% 기본 저항을 가지고 쳐맞을 때마다 받는 딜을 어썸하게 감소시키는(....) 악마의 능력.)의 마이너 버전으로 갑옷을 뽑았습니다...만, 굉장히 구져 보입니다. 하지만 모르잖아욧/?????? ? ? ? 빼애액애애ㅐ이ㅐ이ㅐㅐㄱㄱ

죄송합니다 버프하겠습니다

TTMP의 상...징?인 책QC의 강화 버전도 존재합니다. 바로 활책 시리즈(?)로, 말 그대로 화살이 나가는 책(...)입니다.

공통점으로는 우클릭으로 사용해서 화살을 발사하며, 모두 양손에 끼고 쏘거나 우클릭을 꾹 누르고 쏘는 것이 가능합니다. 정신 집중이 아니니 느려지지 않는 것도 장점이라면 장점. 책QC 베이스여서 근접 공격 대미지도 붙어 있습니다.

첫 번째 주인공은 초반용 구데기 활책으로, 인벤토리에 있는 화살을 하나씩 쏩니다.

일반 활보다 대미지도 적고, 화살도 느립니다. 하지만 근접공격과 원딜공격을 한 번에 행한다는 것이 어쩌면 매우 좋은 것일 수도 어쩌구 저쩌구

또한 이 구데기를 두 가지 방향으로 업그레이드할 수 있습니다. 바로 대포 추진식 화살 발사기와 신비한 화살의 마도서입니다. 죶같은 네이밍 사과드립니다.

대포 추진식 화살 발사기는 사용하면 굉음과 함께 빠른 탄속의 화살을 4발 뿌립니다. 화살은 인벤토리에서 소모하지는 않고, 그냥 생성됩니다. 대신 아이템은 드랍하지 않습니다. 그야 드랍하면 사기지

이 화살은 무적시간이 돌아가는 상대를 때릴 경우 무적시간을 초기화하고 조금 낮아진 대미지로 뚜까팬 다음 그 상대를 그대로 관통해서 지나갑니다. 즉 그냥 쏴서 전부 맞추기만 해도 3발이 관통해서 뒤쪽으로 가며, 원한다면 근접 공격으로 때리고 바로 쏴서 4발 전부 관통하도록 할수도 있습니다.

근접 공격 얘기가 나와서 말인데... 기본 공격력도 센 편입니다.

신비한 화살의 마도서는 사용하면 빠른 탄속의 화살을 8발(...)발사합니다. 이 화살도 인벤토리에서 오지 않고 생성됩니다.

이 화살은 중력의 영향을 받지 않으며, 지형지물을 관통하여 움직입니다. 또한 맞은 상태에게 졸라게 아픈 딜을 넣는 것 이외에도 짧은 시간 동안 공중 부양 상태로 만듭니다.

두 책 다 사기인 것 같긴 한데.. 뭐가 좋은지는 아직 잘 모르겠습니다. 아무튼 대포추진식이 뽕맛이 엄청납니다. 쾅쾅 소리나면서 막 그러니까 막 뚝배기 깨지는게 200% 실감되는데...잘 생각해보면 마도서쪽이 딜링은 잘 될 수도..

그리고 크리에이티브 모드 전용 활책인 기관단궁이 있겠습니다. 이제 보니 책이라 안 부르고 활이라 적어놨네

이 녀석은 사용하면.... 초고속으로 비행하는 대포추진식과 같은 종류의 화살을 초당 40회 발사합니다. 당연히 이 녀석도 양손에 하나씩 낄 수 있으니, 최대 80발/s 되겠습니다.


결론:사기템

그리고 1.7 시절에 구현해서 사용했던 아이템 안대가 돌아왔습니다. 안대는..전과 비교해서 바뀐 건 거의 없고, 끼면 약간의 방어도와 저항, 힘, 나이트 비전 효과를 받지만 동시에 실명 효과도 같이 받습니다.

또한 옆에 보이듯이 살게라스의 시야 업그레이드가 가능합니다. 살게라스의 시야 업그레이드를 붙이면 실명 효과가 걸리지 않습니다. 으어어어어어썸!

마지막으로 두 개의 크리에이티브 전용 아이템, NaNinator과중력 스태프입니다.

(개발 중 스샷이어서 자주검정입니다 재성)

NaNinator는 칼처럼 생겼지만 칼은 아니며 아무런 대미지도 붙어 있지 않습니다. 엔티티를 때려서 체력을 NaN으로 설정할 수 있으며, 우클릭을 하여 자신의 체력까지 NaN으로 만들 수도 있습니다. 이미 체력이 NaN인 상대에게 효과를 가하면 최대 체력으로 돌아옵니다.

NaN이 된 엔티티는.... 죽지도 않고 대미지를 입지도 않습니다. /kill @e도 먹히지 않습니다. 존나 극딜 퍼부으면 죽어버리는 개호구같은 GER보다도 더욱 GER에 가까운.....? 읍읍

플레이어의 경우에는 움짤에서 보시다시피 화면이 기울어진 채로 엄청나게 흔들립니다. 아마 사망 모션을 진행하는 것 같은데 좀 거슬립니다(.....)

( + NaN이 뭐냐?

NaN은 컴퓨터가 처리하는 실수Real Number의 영역 중 하나로, 정의되지 않은 값을 나타낼 때 쓰입니다. 실수 0을 0으로 나누거나, '무한'을 0으로 곱하는 등의 해괴한 연산의 결과로 NaN을 만들 수 있습니다. 복소수가 나오는 연산 또한 NaN을 반환합니다. 컴퓨터가 정의하는 숫자의 영역은 실수가 전부이기 때문.

NaN은 모든 수와 다른 것으로 연산되며(자신과 비교할 때도), 거의 모든 NaN을 사용한 연산은 NaN을 반환합니다.

IEEE 754의 항목을 조금 더 찾아보시면 컴퓨터의 Floting Decimal에 대한 자세한 정보를 알아볼 수 있습니다.)

(이것도 개발 중 스샷이어서 자주검정입니다. 재성ㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎ)

과중력 스태프는 매우 간단하게, 사용하면 커서가 있는 위치 주변에 있는 모든 플레이어를 제외한 살아 있는 엔티티를 끌어당깁니다.


어이쿠야 이거 적어놓고 보니 틱퍼널은 틱퍼널이 아니라 더 많은 무기 추가 모드같은데 어흠흠..

뭐.. 무슨 능력이 있든 뭔 상관이예여. 어차피 틱팀이 만들었으니 다 뚝배기 깨는 미친놈들이겠지


그리고, 틱팀이 강철 제련하는 타일엔티티의 모델을 만들다가 건축뽕에 아주 제대로 맞아버린 관계로, 몇 가지 가구도 추가합니다. 대단한 건 아니고 그냥 광원 몇몇 개에 머시기 머시기.....

나무 몇 개와 종이 석탄 조금으로 싸게 만들 수 있으며, TTMP에서는 확정밴입니다.(??


여기까지가 틱퍼널...아니, 정식명칭인 Tictim's MobCapabilities의 오버뷰. 지금 꽤 빡시게 작업하고 있으니 나중에 좋은 성과를 볼 수 있을 수도 있고 아닐 수도 있습니다.


또한 지금은 작업하고 있지 않지만 기술모드를 만지고 있습니다. 이름은 Assembly로, 여러 부품들을 모아 조립해서 커스텀 기계를 만드는 컨셉의 모드입니다.

조금 구현이 어렵기도 하고 구상이 너무 많은 게 흠이기도 하지만 뭐...

어떻게든...되겠죠.....무ㅠㅓ..........

전자레인지들

진짜 전자레인지는 아니고, 저 기계에 모듈을 꼬라박고 렌치로 탕탕 치면 기계가 됩니다.

그렉텍이 빙의한 재료 아이템 리스트

...

...


아뇨 그렉텍과는 다릅니다! 저는 손수 존나 텍스쳐 노가다로 찍은 고퀄리티 텍스쳐라구욧!뺴얘얘ㅒ얘ㅐㅐㄱ

위의 리스트들은 뻥튀기고, 광물/주괴들만 모은 사진.

새로 추가되는 광물들은 순서대로 구리, 주석, 니켈(^^), 티타늄.

합금이나 광물이 없는(?) 금속들은 아래 줄입니다. 순서대로 청동, 인바(^^^^^^), 강철, 라피시움(?), 엔더륨.

그렇습니다...틱팀은 써멀에 영혼을 팔아버린 한심한 작자입니다....저에게 돌을 던지십시오.....


어셈블리는 보여드릴 게 많이 없네요. 부들부들



그리고 다가오는 TTMP Core 1.6.3.0에서는 추가 탭에 각각 아이콘을 달았습니다. 이제 책QC 복붙은 Naver Daum......

기존 hungerKeeper같은 모드들은 코어모드 탭의 아이콘을 덮어쓰기해서 썼습니다만, 이제는 아이콘이 고정되어서 덮어쓰기가 안 됩니다. 히히.



마지막으로, 구상하고 있는 바이옴 추가..? + 지형/지물 추가 모드 "Quadema"가 있겠습니다. 구상 뿐이고 구현할 수 있을지는 의문입니다만 어떻게든 되겠죠 껄껄 깔깔 아 너무재밋다



+ TTMP에서는 모딩 인력을 모집하고 있습니다.

라기보단, 모딩하는 사람들끼리 모여 서로 정보와 성과를 교환하고 필요할 때 도와주는 식의 그런...뭐시기입니다.

공지 목록의 [TTMP에 관심이 있으신 분들께 드리는 말씀]에서 설문지를 작성해 주세요!




공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]

Posted by Tictim indie.

아누 도라! 틱팀입니다. 새 모드를 만들었습니다. 이름하야 GhostUtilities. 테러블 테러블한 작명센스 인정합니다.

고스트유틸은 매우 작은 클라이언트 전용 모드로, 유용한 HUD와 오버레이의 추가에 초점을 맞추고 있습니다.

하지만 솔직히 말해서 NEI F7 기능밖에 없습니다



GhostUtilities[1.0.0.0]

Minecraft 1.10.2

Forge +12.18.3.2185


본격 오버레이 모드. F7 키를 이용해 켜고 끌 수 있으며(수정 가능), 다음과 같은 기능을 제공합니다.

밝기 오버레이 : 주변의 몹이 스폰될 수 있는 바닥에 X표시를 합니다.

NEI의 밝기 오버레이와 동일한 기능이죠. 밤낮에 따라 밝기가 바뀌는 공간은 노란색 X로, 동굴 같이 밤낮 내내 어두운 공간은 빨간색 X로 표시합니다. 횃불 등등으로 와딩을 했을 경우엔 X표시가 나타나지 않습니다.

광원 미리보기 : 오른손에 든 광원을 해당 블럭에 놓았을 때 몹 스폰을 막는 범위에 초록색 마름모 표시를 합니다.

이건 베끼지 않았습니다(자부심). 횃불 등등을 오른손에 들고 벽이나 바닥 같이 클릭 가능한 블럭에 마우스를 대면, 몹 스폰을 막는 범위에 초록색 마름모 표시를 합니다.


이 모드는 아직 개발중입니다. 너무 컨텐츠가 적은 건 알지만 넣을 게 없다구요. 부들부들부들부들

댓글에 아이디어 좀 기재해주세요. 이런 거 있으면 편하겠다 하는 HUD나 오버레이 같은 거요.


이상 짧은 모드 리포트였습니다. 감사합니다.

그럼 틔틘은 또 잠수하러 간다구




공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]


Posted by Tictim indie.

수정 전.

수정 후.



@SideOnly는 클래스고 메소드고 뭣이고 상관없이 붙어있는 내용물을 뒤틀린 황천으로 같이 끌고 간다는 걸 알려 드린 적이 있습니다. 바로 이전 글이죠. 그리고 이 @SideOnly 처리도 Transformer를 이용하는 것 같습니다. 저번에 화로 만졌던 그거 있죠? 그런 걸 쓴다는 겁니다.


그런데.. FMLLoadingPlugin 클래스에 붙이는 @TransformerExclusions가 제 발목을 잡았습니다. 이 어노테이션은 세상에나 세상에나 Transformer의 수정을 방어하는 기가 막힌 능력을 가졌습니다. 해당 어노테이션으로 전달한 문자열로 시작하는 package를 가진 클래스는 로드될 때 Transformer#transform(...)가 호출되지 않습니다.


그런데 제가 그만 착각을 해 버렸습니다. 위 설명대로 전달한 문자열로 시작하는 package를 가진 클래스를 보호하는 옵션을 전달한 문자열과 동일한 package를 가진 클래스를 보호하는 것으로 착각해 버린 것. 


덕분에 두 개만이 적용되어야 했던(틱팀이 그렇게 착각했던..) Transformer Exclusions의 범위는 TTMP Core의 패키지 전체로 확대되어 버렸고, 따라서 바이트코드를 날려버리는 @SideOnly도 TTMP Core에서는 작동하지 않았습니다.



다음 상황은 불 보듯 뻔합니다. @SideOnly가 붙은 클래스를 사용하는 메소드는 해당 클래스 자체도 없어지기에 @SideOnly로 없애 주어야 "이 클래스 무슨 클래스냐"에러가 발생하지 않습니다. 그런데 @SideOnly의 효과가 TTMP Core에서는 없었으니 메소드도 안 사라졌고... DefaultStateMapper(로그에서는 IStateMapper)도 찾을 수 없었습니다.


..이상 틱팀의 디버깅 일지였습니다. 계속 TTMP Core에서 똥을 싸대면서 이거 왜 안돼냐 빼애액거리고 있다가 멘탈이 거세게 나가서 아무 클래스나 열어보면서 지푸라기라도 잡아 헤매고 있다가 IFMLLoadingPlugin의 저 어노테이션을 보는 순간 뇌에 벼락을 맞은 기분이었습니다.

뭔가 프로그래밍을 하다 보면 수상한 부분을 잘 찾아내게 되는 기분입니다(...). 실수하는 양은 변함이 없지만서도 말입니다. 깔!깔! 이게..아닌데...



여러분 TTMP는 안전합니다. 빨리 슈퍼너프의 세계로 오십시오.




공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]


Posted by Tictim indie.

앙녕하새오. 틱티밈니다.

할마리업슴미다. 앙넝히게세오.



틱팀. 모딩근황.



ASM. 성공. 틱팀. 진화.


1.10.2 환경에 발을 들인 이후로 틱팀의 잉여력은 하늘을 찌르고 모드도 날이 갈수록 더 병신같아지고 있읍니다. 이번엔 대놓고 너프폭격을 가하는 모드를 만들었으니 그 이름은....


TTMP SUPERNERF


..대놓고 이름이 슈퍼너프인 모드 되겠습니다.

TTMP SUPERNERF는 TTMP에 있으면 재밌을 것 같은 너프를 모아서 만든 모드입니다. 그 내용물은

플레이어의 무적 시간 제거 (<<켜고 끄기 가능)

용암 버킷 연료에서 제거 (<<켜고 끄기 가능)

플레이어/몹 영구 투명화 (<<켜고 끄기 가능)

플레이어 영구 실명 (<<켜고 끄기 가능)

어두운 곳에 있을 시 '공포'에 의해 피해를 입음 (<<켜고 끄기 가능)

젖었을 시에 '추위'에 의해 피해를 입음 (<<켜짐, 추운 바이옴에 있을 때 한정, 꺼짐으로 조절 가능)

코블스톤 설치 불가 (<<켜고 끄기 가능)

나무 판자 설치 불가 (<<켜고 끄기 가능)

횃불 설치 불가 (<<켜고 끄기 가능)

모든 토끼를 킬러 버니(타입 99, 플레이어를 확2타로 보내버리는 무시무시한 선공몹입니다)로 변신시킴 (<<켜고 끄기 가능)

클라이언트 감마 강제 조정


이 있습니다. 이거 다 적어놓고 보니 뭔가 TTMP에서 몇 개나 켤수 있을지도 의문이 드는....음...크흠... 아무튼.

이 모드는 너프만 하는 모드는 아닙니다. 몇 가지 유틸리티 기능을 추가하죠. 유틸리티 기능이란

NEI F7(밝기 오버레이)

주울 수 없는 멈춰 있는 화살 제거

되겠습니다.


...예. F7 기능은 뜯어왔습니다. 으하하하!!! 그야 NEI는 너무 무거우니까요. 좆까 NEI 너의 정체성은 이미 사라졌어


먼저, 화살 제거는 서버의 틱 관리를 위해서 추가했습니다. TTMP는 이게 없으면 서버가 굉장히 몸살앓이를 할 것 같은(...) 환경이거든요.

공개하지 않았지만 지난 달의 테섭에서는 엄청나게 짧은 연사속도와 미친듯한 어그로 범위로 인해 TTMP의 에임핵 한조(..)들은 화살 렌더링으로 TTMP 클라이언트의 프레임 드랍을 책임지는 필수요소가 되었습니다. 그래서 플레이어 배려 차원(...)에서 화살을 제거하게 되었습니다.


또 NEI의 F7(밝기 오버레이)가 뭔지 모르시는 분들을 위해 설명드리자면, 주변 블럭의 밝기를 측정하여 몹이 스폰되는 곳에 노란색/빨간색 X표를 쳐 줍니다. 지상 같이 밤낮에 따라서 몹 스폰 여부가 갈리는 곳은 노란색, 동굴 같이 항상 어두운 곳은 빨간색.

이런 식이죠.

그런데 이걸 가지고 있는 모드가 NEI다 보니, 클라이언트가 상당히 무거워질 수밖에 없었습니다. 그래서 틔틘의 인생철학 "좋으니까 베낀다"를 따라서 뜯어왔습니다. 베끼는 것도 꽤나 힘들었던 건 안비밀. 진짜입니다. ㅅㅂ 왜 NEI는 JEI도 깔고 앉고 코드치킨코어도 깔고 앉는데 코드치킨코어는 지가 깔고 앉는 코드치킨 라이브러리 탑재는 안 해주는지. 진짜 비대해질대로 비대해진 돼지뚱땡이입니다. 님들 다 NEI 쓰지마셈. 좆구림.


또한 이 모드에 데스카운터를 넣을 생각입니다. 그러니까 지금까지 HQM에서 갖다 쓰고 있던 사망 페이지를 이 모드에 병합해버리겠다 이겁니다. 뭔가 TTMP 전용 모드가 되어가고 있는 듯 하지만 반은 사실이니 부정하지 않습니다.

..사실 저도 그런 거창한 거 만들긴 어렵고 계속 HQM을 쓸 생각이었습니다만,.....

HQM의 제작자가 단 한 번도 UUID를 써 본적이 없는 듯이 초보적인 오류를 뿜어버리는 바람에 정이 떨어져서 갈아타게 되었습니다.


JAVA알못들을 위한 설명충 등판

UUID는 JAVA에서 기본으로 제공하는 클래스 중 하나이자 식별자 표준입니다. 이 UUID는 엔티티가 가지고 있으며 월드에 똑같은 UUID를 가지고 있는 엔티티는 생성되지 않습니다. 따라서 UUID로 이 엔티티가 지금 월드에 있는지, 어디에서 뭘 하고 있는지 등등을 알 수 있습니다. 플레이어가 로그인할 때 뜨는 "UUID of player ~~~ is 9167c025-21ab-4c72-8cc3-b20ec2bf4277" 하는 식의 문자열의 뒷부분이 바로 UUID입니다.

그런데...이 UUID는 엔티티가 가지고 있는 겁니다. UUID라는 클래스 자체는 마인크래프트에 대해서 아무것도 모릅니다. "Tictim"이라는 단어를 주고 UUID를 받으려 해 봤자 받는 건 9167c025-21ab-4c72-8cc3-b20ec2bf4277같은 UUID "표기법"을 지키지 못해서 일어나는 크래시 뿐입니다. 왜 저런 초보적인 실수를 했는지 모르겠지만.. 암튼 이런 모드를 TTMP에는 넣을 수 없었습니다(....). 반성하세요 HQM


...이상 잘난척이었습니다.


그리고 용암 버킷 연료 삭제는...꽤 힘들었습니다. 아니 엄청 힘들었습니다. 지금도 힘듭니다.


화로의 타일엔티티는 기본적으로 static method에서 burn time을 얻도록 되어 있습니다. 그런데 이 static method가 아무런 이벤트 비슷한 처리도 없이 바닐라 아이템을 만져버리니 아예 바닐라 아이템을 수정할 수 없었던 것.

1.10.2 하지 마라


덕분에 TTMP Core는 진정한 코어모드의 길로 들어서게 되었습니다...바로 ASM이죠.



ASM이란... 이 프로그램의 구성 요소를 뿌리부터 지우고 다시 쓰는 기술입니다. 유용하지만 위험하고 호환성을 해치며 별로 추천되지는 않는 기능이죠. 마인크래프트에서는 해당 기능을 코어모드의 형태로 지원합니다. Loading Plugin이라고 해야 하나요? 잘 모르겠습니다. 허허.

아무튼... 화로의 메소드를 뜯어버리기 위해서 해당 기능을 넣게 되었습니다. 이걸 만들기 위해서 갈려나간 과거의 틱팀의 멘탈에 X키를 눌러 Joy를 표하십시오. XXXXXXXXXXXXXXX.


..농담이 아니고 진짜 힘들었습니다. 하 ㅅㅂ 왜 그렇게 복잡한 건지... 그리고 왜 모든 것은 만들어 놓고 보면 그렇게 간단해 보일 수가 없는 건지.................하.............................

 이 Transformer는 변신하는 고철덩어리...가 아니라! ASM을 구사하는 마법의 클래스입니다.


그렇게 맨 위 짤이 탄생하게 되었습니다. 죽어라 마인크래프트....죽어라...모장....

슈퍼재탕


허나! 안일해진 틱팀의 눈앞을 가로막는 거대한 장벽이 하나 더 있었으니....

바로 SideOnly 에러 되겠습니다.


SideOnly란, 마인크래프트가 서버와 클라이언트를 나누는 기준?입니다. SideOnly(CLIENT)클라이언트에서만 존재하고, SideOnly(SERVER)Dedicated 서버, 즉 jar파일로 배포되는 서버 파일에서만 존재합니다. 그런데 SideOnly의 작동 방식이 웃긴 게, @SideOnly라고 표시된 것들이 있으면 밑도 끝도 없이 그냥 날려버립니다. 지워버린다는 얘기죠. 따라서 @SideOnly가 붙은 것들에 접근하게 되면 서버(혹은 클라이언트)가 즉시 터져버리게 됩니다.

여기서는 Dedicated 서버를 실행했을 때 존재하지 않는 클래스인 IStateMapper를 발견했고, 이 클래스를 로딩하는 중에 오류가 발생해 버린 것.

평범한 SideOnly 실수라면 쉽게 고칠 수 있었겠지만 이건 그렇게 쉽지가 않았습니다. IStateMapper는 분명 로드되지 않는 위치에 있었고, 이 위치에서 계속 크래시가 일어나니 틱팀의 멘탈은 이미 가루가 되어 하늘을 날아다니는 중.


이 오류는 아직도 고쳐지질 않고 있습니다. 먼저 가장 의심되는 TTMP Core에서 Block으로 여러 실험을 해 볼 생각. 그게 안 되면....음....글쎄요. TTMP가 해체될 수도 있습니다(극단적)


넝담입니다. 반드시 고쳐서 어썸한 근황 싸지르도록 하겠습니다. 이상 틱팀이었습니다. 똥글 다 읽어 주셔서 감사드립니다. 사랑과 관심 환영합니다. 지적과 훈수도 환영합니다.


그리고 존잘님..........Block 문제 맞는 거 같아여...........도와주세여.........................


불에 닿은 지 1초....목숨을 잃었다....

▲ 어썸한 차회예고. 어썸한 틔퍼널의 어썸한 근황을 보시라



++ 알아도 안 좋은 사실들

해당 모드는 틱팀의 모드 중에서 가장 가벼운 모드입니다. 2위는 워터싱크입니다. 하지만 코어모드가 무거우므로 무거운 모드입니다.

TTMP SuperNerf의 아이콘은 이상한 꿈틀꿈틀 머시기입니다....꿈틀꿈틀 머시기가 상징하는 의미는 하찮은 5마리 플라나리아의 정월대보름 축제합일입니다. 하나가 되자!

저 SideOnly 오류는 이제 릴리즈겠지?라고 생각한 안일한 틱팀이 모든 모드를 버전업시키고 빌드한 다음 배포하기 직전에 테스트하던 찰나에 발견되었습니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ큐ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ




공지 목록


[TTMP에 관심이 있으신 분들께 드리는 말씀]


[코노조에 어서오세요]


Posted by Tictim indie.

인퍼널 몹 한정으로 디스폰 옵션을 꺼 봤더니 개판이 나 버림


그러나 이 좀비가 다시 떨어지는 일은 없었다. 스폰 0.1초만에 하늘로 솟구친 그는 거짓말 같이 디스폰되어 영영 볼 수 없게 되었따.


본격 /kill @e(플레이어, 아이템을 포함한 모든 엔티티를 죽임) 내성 골드 E 레퀴엠 틔퍼널 좀비.




... ... ...



아 아닙니닷! 이거 알파입ㅂ니닸!





P.s. 저 슬픕니다.

마크야 아프지마

Posted by Tictim indie.