Перед вами будущий учебник для начинающих модостроителей Minecraft'а.
Намечается написать целых 20 глав для новичков.
Так же скажу от себя - моддинг под данную игру может быть и не очень сложен, но он отнимает много времени и от вас потребуются железные нервы.
АХТУНГ! УЧЕБНИК ПО МОДДИНГУ ДЛЯ MODLOADERA!
КОД НА ИЗОБРАЖЕНИЯХ ПРОВЕРКИ МОЖЕТ ОТЛИЧАТЬСЯ ОТ КОДА УЧЕБНИКА! НАПРИМЕР: ID ОБЪЕКТА.
ИСПОЛЬЗУЙТЕ КОД КОТОРЫЙ УКАЗАН В ГЛАВАХ И ПРОВЕРЯЙТЕ РЕГИСТР НА КАРТИНКАХ!
Вопрос-ответ:
Вопрос: Чем этот учебник отличается от статей WD'kun'a?
Ответ: В данной учебнике больше информации и моддинг осуществляется для клиента с ModLoader'ом.
Вопрос: А зачем этот ModLoader?
Ответ: Делает удобнее и быстрее моддинг в разы.
Вопрос: Я сделал свой первый мод, куда мне можно его залить и кому показывать?
Ответ: Если вы уверены, что Ваш мод достоин внимания и он хорошо проработан как и в плане оптимизации, так и в плане внешнего вида - скидывайте его на minecraftforum.net
Вопрос: А что если у меня не лицензионная копия игры? Я не смогу делать моды?
Ответ: Моды можно делать и на пиратке, на счет этого не беспокойтесь. Разницы нет.
Вопрос: Я там карочи всие сделол как написана и игра паказывает англиские слава какие та ниче ни понятна!!111
Ответ: Для того, чтобы мы Вам помогли, скиньте Log'и (текст) ошибки прямо в эту тему, мы Вам обязательно поможем!
Вопрос: При рекомпиляции выпадает море ошибок. Что делать?
Ответ: Отписать в эту тему или в джаббер конференцию. Если никто Вам не отвечает, проверьте, все ли скобки стоят правильно и совпадает ли регистр букв.
Вопрос: Я зашел в конференцию, а там никого нет? На форуме не отвечают, в конфе тоже пусто. Вы пропали?
Ответ: Скорее всего из авторов учебника никого нет в сети. Будьте терпеливы, как только появится возможность, мы Вам обязательно поможем!
Вопрос: У меня ничего не получается! Сделайте, пожалуйста за меня ...
Ответ: Мы делаем что-то для пользователей только в крайних случаях, если например ошибки неизлечимы, и все это связанно с вашим компьютером, а не руками.
Вопрос: Я прошел весь учебник, но обновлений не наблюдаю. Вы забросили его?
Ответ: Конечно же нет! Просто у нас тоже есть личная жизнь, и иногда приходится отлучаться.
Вопрос: Я видел у буржуев статью про ... Вы добавите ее к себе?
Ответ: Добавьте ссылку на источник статьи, мы ее прочитаем, проверим, проанализируем и запишем по своему
Вопрос: Все время вы говорите создать какой-то файл .java. Как его вообще создать?
Ответ: Создаете текстовый файл и просто переименовываете его из Текстовый документ.txt, например, в mod_gcc.java (открывая его, непосредственно, в нотепаде), а затем редактируете и сохраняете.
Вопрос: В учебнике слишком неудобно отписаны некоторые моменты. Можно я какие мне надо строчки в другие файлики перемещу, ведь так удобнее!
Ответ: Ни в коем случае! И даже не пытайтесь.
Вопрос: А как открыть файл .jar винраром?
Ответ: ПКМ --> Открыть с помощью --> WinRar или 7zip.
Вопрос: Я начал работать, но в src/minecraft/ файлов нет! Я что-то забыл сделать?
Ответ: Скорее всего, декомпилятор выдал ошибку и не отдал вам сорцы игры. Ну или в крайнем случае вы просто забыли его включить.
Скрытый текст
Глава 1. Подготовка рабочего места и настройка MCP.
Я отказываюсь писать статьи по старому стилю оформления как в прошлых уроках, т.к надоедает все время отписывать числа.
Надеюсь, вы меня поймете
Требования:
- Установка:
1. Создаем папку в любом удобном для вас месте.
2. Копируем файлы архива MCP в эту папку.
3. Прописываем путь к javac.exe (JDK) в системной переменной PATH.
Щелкните правой кнопкой мыши по ярлыку Мой компьютер и выберите категорию Дополнительно. Там же ниже будет кнопка Переменные среды.
В системных переменных найдите переменную Path (PATH) и допишите в ней строки:
Без пробела и с символом "точка с запятой". Путь укажите, конечно же, по вашему усмотрению системы.
4. Кладем из клиента Minecraft папки bin и resources в папку jars, которая непосредственно находится в вашей папке которую вы подготовили ранее (о как сказанул Нотч ).
5. Откройте папку bin и найдите minecraft.jar. Откройте (не разархивируйте), и удалите папку META-INF.
6. Запускаем decompile.bat.
7. Как только вы пройдете уроки ниже, просто напросто запускайте recompile.bat, а после чего startclient.bat и тестируйте.
8. Ну а когда вы точно решили что мод готов - запускайте reobf.bat, проходите в папочку reobf и все содержимое кидайте в файл minecraft.jar специально подготовленной для этого игры.
Глава 2. Создание блока.
Запоминайте сразу, в пути \src\minecraft\net\minecraft\src находится весь декомпилированный код игры.
Для начала давайте создадим новый файлик посредством нотепада. Называться он будет mod_gcc.java.
Он служит для складывания всей информации о блоках, рецептах, etc.
Впишем такую строчку (используйте Notepad++, детишки!).
После чего добавим еще две строчечки, но сначала делаем пробел.
Давайте попробуем разобрать данную неразбериху.
Число 101 - айди блока. Используйте с 101 по 250.
Число 0 - не трогайте, это индексация текстуры по terrain.png, оно вообще не понадобится. Пусть стоит в фазе нуля.
1.0F - светится как австралий.
Профиряем.
Теперь давайте создадим специальный файлик BlockNew.java (по названию блока) который определит наш кубик в игре.
Вписываем в первую строчку магические буковки, опять.
Дальше объявляем выбрасывание и его ID.
Примечание: У меня там Rock написано в свойстве, пропустите это, ага.
Если все так же - переходим к следующей главе.
Глава 2.1. Рецепт для блока или как добыть кубик.
Добавим четыре строчки для определения версии вашего мода (писать можно что угодно).
Запишем вот это:
Регистрируем блок строкой:
Одна решетка обозначает одну ячейку сверху вниз (это может быть и верстак, если решеток более 3 в одной строке).
Т.е. в нашем случае мы заполняем обычной землей (Block.dirt) все крафт-ячейки в инвентаре (их 4).
Для примера, если например ваш объект крафтится не только из земли, да еще и в верстаке, поступать нужно так.
Если какой-то символ (в нашем случае решетка) не указана в Character.valueOf - то значит дефолтно ячейки должны быть пусты (заменяйте пустые ячейки символом #!)
Проверяем.
Вот и все. Теперь ваш блок можно спокойно скрафтить.
Но мы забыли добавить текстуру, о нет! Об этом читайте в следующей главе.
Глава 2.2. Присваиваем текстуру.
Эта глава очень короткая и легкая, но все же я выделил ей особое место.
Берем вот такую текстуру:
(размеры не изменять!)
И временно кидаем ее в папку jars/bin.
Заходим в папку bin, находим minecraft.jar, открываем ее посредством WinRar или 7-zip и создаем там папочку textures.
И в эту папочку кидаем нашу текстуру java.png.
Теперь открываем mod_gcc.java и добавляем строчки рядом с рецептом.
Вот и все!
Проверяем.
Если вы уверены что все сделали правильно, запускайте recompile.bat, проверяйте на наличие ошибок (если есть, отписывайте с вопросами сюда), после чего включайте startclient.bat и наслаждайтесь вашим творением!
Скриншот из игры:
Глава 3. Создание предмета.
Для начала добавим одну строчку:
Делаем отступ на одну строку от строки:
И последняя строка рецепта.
Теперь нам нужно создать файлик Smile.java.
В первой строке как обычно:
Глава 3.1. Присвоение текстуры.
Возьмем текстуру смайлика
(размеры не изменять!)
И поместим ее в minecraft.jar/textures как обычно.
Пишем после рецепта:
Проверяем.
Теперь вам осталось просто запустить recompile.bat и опробовать смайлы
Скриншоты из игры:
Глава 4. Генерация блока в мире.
Сейчас я попробую рассказать, как заставить наш блок генерироваться в игровом мире.
Для примера он будет появляться у камня (2-3 блока вниз).
Откроем mod_gcc.java.
После первой строки добавьте строку:
А после 13 строки сделаем отступ и запишем вот это.
Число 150 отвечает за редкость блока в игровом мире. 150 - это почти вездесущий, и его будет дохрена.
Для теста 150 подойдет отлично. Далее просто экспериментируйте.
http://savepic.net/1794021.htm
Вот и все. Запускайте и пробуйте!
Скриншоты из игры:
Глава 5. Создание еды или как слепить хавку.
Добавляем к пабликам строку:
Первое число - ID, второе - количество половинок сердца для восстановления (всего 20 половинок), а false можно ли использовать на волке для привлечения. Далее все по прежнему.
http://savepic.ru/2966715.png
(размеры не изменять!)
Создаем файлик pigHead.java.
Туда кидаем:
Для развития:
Если хотите чтобы после поедания вашей еды выпадал предмет (например, если это суп), вместо старого паблика впишите новый:
Тут все очень просто.
Открываем BlockNew.java.
Ищем:
Выкидываем палочки. Для дропа своих итемсов - пишите mod_gcc.nameItem.shiftedIndex - nameItem - название предмета.
Для дропа блоков - названиеблока.blockID.
Для дропа СВОИХ блоков или того же блока (по типу руды) - mod_gcc.названиеблока.blockID.
http://savepic.net/1798137.htm
Вот и все. Пробуйте!
Глава 7. Создание нового инструмента (на основе стандартных материалов).
Сейчас мы сделаем веник. Он будет у нас аналогом алмазного меча.
Добавим к пабликам строку:
Обозначаем что это за предмет. Есть sword, axe, pickaxe и spade. В нашем случае - меч.
WOOD - Дерево
STONE - Камень
IRON - Железо
EMERALD - Алмаз
GOLD - Золото
http://savepic.net/1777423.htm
(размеры не изменять!)
Тестируем!
Глава 8. Создание нового инструмента и его свойств - Работает!
Открываем EnumToolMaterial.java.
Ищем строку:
Вторая - уровень разрушения.
Сотня - количество разрушаемых блоков в общем (состояние инструмента).
25F - сила разрушения, скорость.
5 - сила удара для мобов.
Сравнивайте со стандартными свойствами и делайте новые.
Теперь просто в mod_gcc, в строке инструмента:
Например:
На данный момент в игре используется только 4 уровня.
0 - дерево.
1 - камень.
2 - железо.
3 - алмаз.
4 - золото.
Открываем ItemPickaxe.java и смотрим код.
Можно заметить что обсидиан разрушается только алмазной киркой - уровнем 3.
Когда стоит строка:
А когда стоит:
Если хотите чтобы ваш блок разрушался только вашей киркой - ставите уровень 5 в свойстве.
Затем дописываем в ItemPickaxe (или что у вас там) новую строку по типу:
Глава 9. Создание нового нейтрального моба - Advanced.
Ну, для начала скажу, что в создании моба нет ничего сложно. Основная проблема, которая может у вас возникнуть, так это создание новой модельки. Я взял обычного крипера и чуть-чуть перерисовал текстуру.
Создаем файл и указываем название mod_freeper.java.
Эта часть кода должна быть уже известна вам, если прошли предыдущие уроки конечно.
Регестрируем моба в нашем мире:
Создаем файл под названием EntityFreeper.java.
Вписываем туда этот код:
(размеры не изменять!)
Тут размеры коллайдера на мобе:
Это отвечает за то, что он будет издавать постоянно. В моем случае он будет кукарекать.
http://savepic.net/1838545.htm
Идем далее.
Назвав файл RenderFreeper.java, мы вписываем в него следующий код:
Начинаем, как всегда с того, что создаем файл и даем ему имя. В данном случае, имя ему будет ModelFreeper.java.
Ну и, наконец, самое главное... модель нашего моба. Чтобы делать модели для minecraft'a, нужна специальная программа, она называется Techne. Впоследствии, возможно мы и напишем пару уроков по “созданию” модели в этой программе. Но пока, скопируйте просто готовый код фрипера. Объяснять тут ничего не надо, так как программа сама все вам сгенерирует.
http://savepic.ru/2997227.htm
От FunnyAlien: Мобы имеют АИ как у обычной свиньи. Бегают, прыгают, улыбаются. Чуть позже мы вместе с Максимом расскажем как сделать вражеского моба и дружелюбного по типу Волка.
От Aswo: Всем привет, я Максим. С сегодняшнего дня я присоединяюсь к Вале, дабы помочь ему и вам в этом нелегком деле. Так же думаю, будет серия уроков по Techne, в которых вы научитесь моделировать объекты для игры. Ну и конечно же добавлять их в игру. В общем, зубрите пока первые девять глав Нотч
Глава 10. Создание нового враждебного моба - Advanced.
Ожидайте.
Глава 11. Создание разностороннего блока.
Копируем данный код, он должен уже быть ясен вам. Если нет, то бегом зубрить предыдущие главы.
Cоздаем файл с именем mod_tex.java дабы не портить mod_gcc и не запутаться.
Далее пишем под публичной блока:
Публичная текстуры с бока:
Путь к текстуре, которя будет боковой:
http://savepic.ru/2985844.htm
Side.
http://savepic.net/1891524.htm
Обычная Tex.
http://savepic.net/1837253.htm
Проверяем.
http://savepic.ru/3004276.htm
Двинемся далее. Cоздаем файл с именем BlockTex.java.
Вот код для отображении текстуры на нашем блоке. Думаю, что потом вам не составит труда отредактировать его для своего следующего блока. В общих словах, вся эта махина создает блок с текстурой Tex. Потом присваивает всем сторонам текстуру TexSide, а уже потом только лицевой стороне присваивается текстура TexFront.
http://savepic.net/1840316.htm
Глава 12. Создание нового моба-помощника. Лучник - Advanced.
Эта статья рассчитана на продвинутых пользователей умеющих делать простейшие моды для майнкрафта, и здесь я попытаюсь рассказать о том как сделать моба который будет вас защищать стоя на месте.
Итак начнем:
Создаем файл mod_BowMan.java в котором мы укажем блок спавна нашего защитника:
Начало такое-же как и в создании нейтрала
Скорость передвижения моба(0.7F - скорость игрока, 0.0F - моб стоит на месте), у нас будет лучник, поэтому скорость 0.
Чтоб наш моб не пропадал.
Здесь в каждую переменную типа list записывается данный о враждебных мобах.
А так объясню только 1 переменную:
Время до следующей атаки (у скелета время = 30, а у нас в 15 раз быстрее )
Остались только текстуры:
Текстура лучника - не требуется (в коде вписана стандартная текстура игрока).
Текстура bowmanegg.png - берем любой файл 16*16 и кидаем в папку textures в minecraft.jar с именем bowmanegg.png.
Ну вот стрелок и готов.
Автор 12 главы: DarkMan.
Мини-глава. Нормальное стекло.
Многие встречались с проблемой, когда после создания "прозрачной" текстуры, через блок можно было смотреть через весь мир, типа X-Ray мода.
Данная проблема решается строчками, которые добавляются в .java блока.
Удачи!
Глава 13. Создание новой брони на основе стандартных материалов.
Добавим к пабликам следующее и разберем:
В нашем случае алмаз.
В нашем случае шлем.
Все как обычно. Текстура должна быть 16x16.
http://savepic.org/2211241.htm
(размеры не изменять!)
Ну и теперь нам нужно добавить текстуру для самой брони на игроке.
Заходим в RenderPlayer.java и крутим в самый конец до строки:
Первая текстура. Обязательно назовите ее titan_1 - т.к префикс "titan".
http://savepic.ru/3041936.htm
(размеры не изменять!)
Вторая текстура. Название - titan_2.
http://savepic.org/2168233.htm
(размеры не изменять!)
Игровые названия делаются не для всего набора брони, а отдельно для каждого предмета из набора (например шлем).
Ну и рецепт так же.
Теперь осталось добавить остальную броню и протестировать.
Удачи!
Глава 14. Использование редстоуна с блоками. Часть 1.
Вот и долгожданная глава, уважаемые читатели!
Тут все на первый взгляд тяжело, но уверяю вас - все очень легко Нотч
Сейчас мы сделаем почти обычный TNT. При подключении редстоуна к блоку - он взорвется.
Откроем наш файлик BlockNew.java и добавим ниже строку:
Устанавливаем силу взрыва.
Вот и все. Осталось только проверить
Экспериментировать можно всегда - сделайте так, чтобы блок не взрывался, а менял свои свойства, прыгал, двигался и прочее. Все действия подглядеть всегда можно в Block.java.
Первая часть главы закончена - я рассказал все самые основы. Чуть позже будет больше
Глава 15. Как создать свою музыкальную пластинку.
В уроке объяснения происходят в самом коде.
Создадим новый mod_musicdiscs.java:
А музыку в папку resources\streaming в формате .ogg и с названием Example и Example2.
Глава 16. Как создать специальный файл настроек мода.
В уроке объяснения происходят в самом коде.
Начнем. Наш блок будет иметь имя firstBlock.
Впишите в mod_prop следующее:
Я отказываюсь писать статьи по старому стилю оформления как в прошлых уроках, т.к надоедает все время отписывать числа.
Надеюсь, вы меня поймете
Требования:
- Установка:
1. Создаем папку в любом удобном для вас месте.
2. Копируем файлы архива MCP в эту папку.
3. Прописываем путь к javac.exe (JDK) в системной переменной PATH.
Щелкните правой кнопкой мыши по ярлыку Мой компьютер и выберите категорию Дополнительно. Там же ниже будет кнопка Переменные среды.
В системных переменных найдите переменную Path (PATH) и допишите в ней строки:
;C:\Program Files\Java\jdk1[paste][/paste]6[paste][/paste]0_25\binили
;C:\Program Files\Java\jdk1[paste][/paste]6[paste][/paste]0_26\binВ зависимости от версии.
Без пробела и с символом "точка с запятой". Путь укажите, конечно же, по вашему усмотрению системы.
4. Кладем из клиента Minecraft папки bin и resources в папку jars, которая непосредственно находится в вашей папке которую вы подготовили ранее (о как сказанул Нотч ).
5. Откройте папку bin и найдите minecraft.jar. Откройте (не разархивируйте), и удалите папку META-INF.
6. Запускаем decompile.bat.
7. Как только вы пройдете уроки ниже, просто напросто запускайте recompile.bat, а после чего startclient.bat и тестируйте.
8. Ну а когда вы точно решили что мод готов - запускайте reobf.bat, проходите в папочку reobf и все содержимое кидайте в файл minecraft.jar специально подготовленной для этого игры.
Глава 2. Создание блока.
Запоминайте сразу, в пути \src\minecraft\net\minecraft\src находится весь декомпилированный код игры.
Для начала давайте создадим новый файлик посредством нотепада. Называться он будет mod_gcc.java.
Он служит для складывания всей информации о блоках, рецептах, etc.
Впишем такую строчку (используйте Notepad++, детишки!).
package net[paste][/paste]minecraft[paste][/paste]src;Она включает магию которая даст возможность данному файлику работать с Кубокрафтом.
После чего добавим еще две строчечки, но сначала делаем пробел.
public class mod_gcc extends BaseMod{Здесь мы создаем класс.
public static Block newblock = new BlockNew(110, 0)[paste][/paste]setHardness(0[paste][/paste]5F)[paste][/paste]setResistance(1[paste][/paste]0F)[paste][/paste]setBlockName("newblock");Пишем в 5 строке вот такие словечки про наш кубик, тут мы его регистрируем.
Давайте попробуем разобрать данную неразбериху.
public static Block newblocknewblock - это название, точнее регистр блока (не путайте с обычным названием, или консоль ошибок покарает вас!).
new BlockNew(110, 0)Ну а вот тут у нас как раз и обычное название. Будет использоваться для обозначения в отдельном файлике для блока (доп. характеристики).
Число 101 - айди блока. Используйте с 101 по 250.
Число 0 - не трогайте, это индексация текстуры по terrain.png, оно вообще не понадобится. Пусть стоит в фазе нуля.
setHardness(0[paste][/paste]5F)Тут у нас крепкость указана. На сколько силен блок, так сказать Нотч Вполне реально хватит и 0.5F если это блок похожий на землю (по скорости разрушения).
setResistance(0[paste][/paste]3F)Устойчивость от взрыва. 0.3F отлично вписывается.
setLightValue(1[paste][/paste]0F)Если хотите чтобы ваш блок был светящимся (для дополнительных команд вызова я выведу чуть позже целый спойлер Нотч ), просто укажите это через точку.
1.0F - светится как австралий.
setBlockName("newblock")Сделан специально чтобы полностью до конца объявить регистр.
Профиряем.
Теперь давайте создадим специальный файлик BlockNew.java (по названию блока) который определит наш кубик в игре.
Вписываем в первую строчку магические буковки, опять.
package net[paste][/paste]minecraft[paste][/paste]src;Затем импортируем еще одну магию которая даст нам возможность использовать переменную Random.
import java[paste][/paste]util[paste][/paste]Random;Потом создаем публичный класс (не забудьте название).
public class BlockNew extends Block{После чего копипастим вот это.
public BlockNew(int i, int j) { super(i, j, Material[paste][/paste]ground); }Тут у нас получается что мы объявляем блок, делаем его настоящим (материальным) и задаем свойство (каждое свойство имеет ряд своих особенностей, типа звуков и т.п).
Дальше объявляем выбрасывание и его ID.
public int idDropped(int i, int j) { return mod_gcc[paste][/paste]newblock[paste][/paste]blockID; } public int quantityDropped(Random random) { return 1; }}
Примечание: У меня там Rock написано в свойстве, пропустите это, ага.
Если все так же - переходим к следующей главе.
Глава 2.1. Рецепт для блока или как добыть кубик.
Добавим четыре строчки для определения версии вашего мода (писать можно что угодно).
public String Version() { return "Tutorial's of Modding!"; }Ну а теперь перейдем непосредственно к написанию рецепта.
Запишем вот это:
public mod_gcc() {И начнем творить.
Регистрируем блок строкой:
ModLoader[paste][/paste]RegisterBlock(newblock);Добавляем название блока в игре.
ModLoader[paste][/paste]AddName(newblock, "GCC");И запюливаем сам рецептик.
ModLoader[paste][/paste]AddRecipe(new ItemStack(newblock, 1), new Object[]{ "##", "##", Character[paste][/paste]valueOf('#'), Block[paste][/paste]dirt});Разберем?
(new ItemStack(newblock, 1)При крафте появляется newblock в количестве 1 (изменяйте как душе угодно до 64).
new Object[]{ "##", "##", Character[paste][/paste]valueOf('#'), Block[paste][/paste]dirtТут очень сложно объяснить для детей, взрослые может быть и поймут, но я все же попробую.
Одна решетка обозначает одну ячейку сверху вниз (это может быть и верстак, если решеток более 3 в одной строке).
Т.е. в нашем случае мы заполняем обычной землей (Block.dirt) все крафт-ячейки в инвентаре (их 4).
Для примера, если например ваш объект крафтится не только из земли, да еще и в верстаке, поступать нужно так.
new Object[]{ "#X#", "#Z#", "#X#", Character[paste][/paste]valueOf('X'), Block[paste][/paste]dirt, Character[paste][/paste]valueOf('Z'), Block[paste][/paste]sandВ данном примере мы ставим землю по середине в верхней строке, ставим песок по середке в средней строке, и опять землю по середине, но только в третьей строке.
Если какой-то символ (в нашем случае решетка) не указана в Character.valueOf - то значит дефолтно ячейки должны быть пусты (заменяйте пустые ячейки символом #!)
Проверяем.
Вот и все. Теперь ваш блок можно спокойно скрафтить.
Но мы забыли добавить текстуру, о нет! Об этом читайте в следующей главе.
Глава 2.2. Присваиваем текстуру.
Эта глава очень короткая и легкая, но все же я выделил ей особое место.
Берем вот такую текстуру:
(размеры не изменять!)
И временно кидаем ее в папку jars/bin.
Заходим в папку bin, находим minecraft.jar, открываем ее посредством WinRar или 7-zip и создаем там папочку textures.
И в эту папочку кидаем нашу текстуру java.png.
Теперь открываем mod_gcc.java и добавляем строчки рядом с рецептом.
newblock[paste][/paste]blockIndexInTexture = ModLoader[paste][/paste]addOverride("/terrain[paste][/paste]png", "/textures/java[paste][/paste]png");Разбираем.
newblock[paste][/paste]blockIndexInTextureСразу предупреждаю, не забывайте изменять название регистра здесь (у меня частенько бывает такое).
ModLoader[paste][/paste]addOverride("/terrain[paste][/paste]png"Не знаю зачем оно, но вроде индексирует размеры блоков внутри terrain.png. Оставляем как есть.
"/textures/java[paste][/paste]png"Ну а тут, непосредственно, указывается путь к текстуре. В нашем случае это java.png в папке textures.
Вот и все!
Проверяем.
Если вы уверены что все сделали правильно, запускайте recompile.bat, проверяйте на наличие ошибок (если есть, отписывайте с вопросами сюда), после чего включайте startclient.bat и наслаждайтесь вашим творением!
Скриншот из игры:
Глава 3. Создание предмета.
Для начала добавим одну строчку:
public static final Item smileItem = new Smile(3000)[paste][/paste]setItemName("smileItem");Непосредственно после строки нашего блока:
public static Block newblock = new BlockNew(110, 0)[paste][/paste]setHardness(0[paste][/paste]5F)[paste][/paste]setResistance(1[paste][/paste]0F)[paste][/paste]setBlockName("newblock");Разберем код предмета.
Item smileItemВызываем предмет по тех. названию.
new SmileНазвание для будущего Smile.java.
(3000)ID предмета.
setItemName("smileItem")Объявляем предмет, даем ему тех. название для идентификации.
Делаем отступ на одну строку от строки:
newblock[paste][/paste]blockIndexInTexture = ModLoader[paste][/paste]addOverride("/terrain[paste][/paste]png", "/textures/java[paste][/paste]png");И записываем следующее.
ModLoader[paste][/paste]AddName(smileItem, "Smile");
(smileItem, "Smile")Даем название в самой игре.
И последняя строка рецепта.
ModLoader[paste][/paste]AddRecipe(new ItemStack(smileItem, 5), new Object[]{ "X#", "#X", Character[paste][/paste]valueOf('X'), Block[paste][/paste]dirt});
(smileItem, 5)Число получаемых "смайлов" после крафтинга.
"X#", "#X" Character[paste][/paste]valueOf('X'), Block[paste][/paste]dirtСам рецепт. По диагонали ставим грязь - получаем смайл.
Теперь нам нужно создать файлик Smile.java.
В первой строке как обычно:
package net[paste][/paste]minecraft[paste][/paste]src;В третьей и четвертой:
public class Smile extends Item{А далее:
public Smile(int i) { super(i); maxStackSize = 64; }}
maxStackSize = 64;Максимальное количество предмета в одном стаке (нап. 64).
Глава 3.1. Присвоение текстуры.
Возьмем текстуру смайлика
(размеры не изменять!)
И поместим ее в minecraft.jar/textures как обычно.
Пишем после рецепта:
smileItem[paste][/paste]iconIndex = ModLoader[paste][/paste]addOverride("/gui/items[paste][/paste]png", "/textures/smile[paste][/paste]png");Разбираем.
smileItem[paste][/paste]iconIndexОпределяет, чья иконка (текстура).
ModLoader[paste][/paste]addOverride("/gui/items[paste][/paste]png", "/textures/smile[paste][/paste]png")Это вам уже знакомо. Тут промолчу.
Проверяем.
Теперь вам осталось просто запустить recompile.bat и опробовать смайлы
Скриншоты из игры:
Глава 4. Генерация блока в мире.
Сейчас я попробую рассказать, как заставить наш блок генерироваться в игровом мире.
Для примера он будет появляться у камня (2-3 блока вниз).
Откроем mod_gcc.java.
После первой строки добавьте строку:
import java[paste][/paste]util[paste][/paste]Random;
А после 13 строки сделаем отступ и запишем вот это.
public void GenerateSurface(World world, Random rand, int chunkX, int chunkZ) { for(int i = 0; i < 150; i++) { int randPosX = chunkX + rand[paste][/paste]nextInt(16); int randPosY = rand[paste][/paste]nextInt(150); int randPosZ = chunkZ + rand[paste][/paste]nextInt(16); (new WorldGenMinable(mod_gcc[paste][/paste]newblock[paste][/paste]blockID, 32))[paste][/paste]generate(world, rand, randPosX, randPosY, randPosZ); } }Разбираем.
Число 150 отвечает за редкость блока в игровом мире. 150 - это почти вездесущий, и его будет дохрена.
Для теста 150 подойдет отлично. Далее просто экспериментируйте.
for(int i = 0; i < 150; i++)150 - высота блока от админиума (бедрока). В нашем случае получается он выше камня на один блок в генерации. Тоже можно экспериментировать.
int randPosY = rand[paste][/paste]nextInt(150);mod_gcc - наш мод. newblock - регистр блока. Число 32 - количество блоков на одном месторождении. Для теста я использовал 32 блока.
(new WorldGenMinable(mod_gcc[paste][/paste]newblock[paste][/paste]blockID, 32))Проверяем.
http://savepic.net/1794021.htm
Вот и все. Запускайте и пробуйте!
Скриншоты из игры:
Глава 5. Создание еды или как слепить хавку.
Добавляем к пабликам строку:
public static final Item pighead = new ItemFood(3001, 10, false)[paste][/paste]setItemName("pighead");Разберем.
Первое число - ID, второе - количество половинок сердца для восстановления (всего 20 половинок), а false можно ли использовать на волке для привлечения. Далее все по прежнему.
new pigHead(3001, 20, false)Запишем привычные строки.
pighead[paste][/paste]iconIndex = ModLoader[paste][/paste]addOverride("/gui/items[paste][/paste]png", "/textures/pighead[paste][/paste]png");ModLoader[paste][/paste]AddName(pighead, "Pig Head");ModLoader[paste][/paste]AddRecipe(new ItemStack(pighead, 1), new Object[]{ "XX", "X#", Character[paste][/paste]valueOf('X'), Block[paste][/paste]dirt});Закинем текстуру в minecraft.jar/textures.
http://savepic.ru/2966715.png
(размеры не изменять!)
Создаем файлик pigHead.java.
Туда кидаем:
package net[paste][/paste]minecraft[paste][/paste]src;public class pigHead extends ItemFood { public pigHead(int i, int j) { super(i, j, true); }}Запускаем и пробуем!
Для развития:
Если хотите чтобы после поедания вашей еды выпадал предмет (например, если это суп), вместо старого паблика впишите новый:
public static final Item pighead = new Head(2001, 20, false, 16)[paste][/paste]setItemName("pighead");Переименуйте pigHead.java в Head.java и весь код замените на:
package net[paste][/paste]minecraft[paste][/paste]src;public class Head extends ItemFood { public Head(int i, int j, boolean flag, int k) { super(i, j, flag); healAmount = j; maxStackSize = k; } public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer) { itemstack[paste][/paste]stackSize--; entityplayer[paste][/paste]heal(healAmount); entityplayer[paste][/paste]dropPlayerItem(new ItemStack(mod_gcc[paste][/paste]pighead[paste][/paste]shiftedIndex, 1, 0)); return itemstack; } public int getHealAmount() { return healAmount; } protected int healAmount;}Единственное что вам тут понадобится - эта строка. После поедания еды выпадает она же в количестве 1. Можете экспериментировать. Для дропа других итемов, пишите Item.название.shiftedIndex.
entityplayer[paste][/paste]dropPlayerItem(new ItemStack(mod_gcc[paste][/paste]pighead[paste][/paste]shiftedIndex, 1, 0))Глава 6. Создание руды или как сделать чтобы из блока выпадали предметы.
Тут все очень просто.
Открываем BlockNew.java.
Ищем:
public int idDropped(int i, int j) { return mod_gcc[paste][/paste]newblock[paste][/paste]blockID; } public int quantityDropped(Random random) { return 1; }}Меняем на:
public int idDropped(int i, Random random) { return Item[paste][/paste]stick[paste][/paste]shiftedIndex; } public int quantityDropped(Random random) { return 2 + random[paste][/paste]nextInt(5); }}Разберем код выше.
Выкидываем палочки. Для дропа своих итемсов - пишите mod_gcc.nameItem.shiftedIndex - nameItem - название предмета.
Для дропа блоков - названиеблока.blockID.
Для дропа СВОИХ блоков или того же блока (по типу руды) - mod_gcc.названиеблока.blockID.
return Item[paste][/paste]stick[paste][/paste]shiftedIndex;Число 2 - минимальное значение дропа. Число 5 - максимальное значение. Значит игра будет рандомно давать вам от 2 до 5 палок с блока.
return 2 + random[paste][/paste]nextInt(5);Проверяем.
http://savepic.net/1798137.htm
Вот и все. Пробуйте!
Глава 7. Создание нового инструмента (на основе стандартных материалов).
Сейчас мы сделаем веник. Он будет у нас аналогом алмазного меча.
Добавим к пабликам строку:
public static final Item venik = new ItemSword(3002, EnumToolMaterial[paste][/paste]EMERALD)[paste][/paste]setItemName("venik");Разберем.
Обозначаем что это за предмет. Есть sword, axe, pickaxe и spade. В нашем случае - меч.
new ItemSwordID.
2002Материал инструмента.
WOOD - Дерево
STONE - Камень
IRON - Железо
EMERALD - Алмаз
GOLD - Золото
EnumToolMaterial[paste][/paste]EMERALDДобавим все как обычно.
venik[paste][/paste]iconIndex = ModLoader[paste][/paste]addOverride("/gui/items[paste][/paste]png", "/textures/venik[paste][/paste]png");ModLoader[paste][/paste]AddName(venik, "Venik");ModLoader[paste][/paste]AddRecipe(new ItemStack(venik, 1), new Object[]{ "XXX", "#X#", "#X#", Character[paste][/paste]valueOf('X'), Block[paste][/paste]dirt});Кидаем текстуру в minecraft.jar/textures.
http://savepic.net/1777423.htm
(размеры не изменять!)
Тестируем!
Глава 8. Создание нового инструмента и его свойств - Работает!
Открываем EnumToolMaterial.java.
Ищем строку:
GOLD("GOLD", 4, 0, 32, 12F, 0),И добавляем ниже новые характеристики:
TITAN("TITAN", 5, 5, 100, 25F, 5);Название.
TITANПервая пятерка - порядковый номер свойства.
Вторая - уровень разрушения.
Сотня - количество разрушаемых блоков в общем (состояние инструмента).
25F - сила разрушения, скорость.
5 - сила удара для мобов.
Сравнивайте со стандартными свойствами и делайте новые.
Теперь просто в mod_gcc, в строке инструмента:
EnumToolMaterial[paste][/paste]EMERALDПишите ваше свойство.
Например:
EnumToolMaterial[paste][/paste]TITANТак же хочу рассказать про уровень разрушения.
На данный момент в игре используется только 4 уровня.
0 - дерево.
1 - камень.
2 - железо.
3 - алмаз.
4 - золото.
Открываем ItemPickaxe.java и смотрим код.
Можно заметить что обсидиан разрушается только алмазной киркой - уровнем 3.
Когда стоит строка:
getHarvestLevel() == 3Значит разрушение происходит ТОЛЬКО 3 уровнем.
А когда стоит:
getHarvestLevel() >= 1То значит, разрушение происходит от 1 уровня до максимального.
Если хотите чтобы ваш блок разрушался только вашей киркой - ставите уровень 5 в свойстве.
Затем дописываем в ItemPickaxe (или что у вас там) новую строку по типу:
if(block == mod_gcc[paste][/paste]newblock) { return toolMaterial[paste][/paste]getHarvestLevel() == 5; }Таким образом только одна кирка сможет разрушить данный блок, а точнее с вашей киркой разрушение пройдет быстрее и из блока может что-то выпасть.
Глава 9. Создание нового нейтрального моба - Advanced.
Ну, для начала скажу, что в создании моба нет ничего сложно. Основная проблема, которая может у вас возникнуть, так это создание новой модельки. Я взял обычного крипера и чуть-чуть перерисовал текстуру.
Создаем файл и указываем название mod_freeper.java.
Эта часть кода должна быть уже известна вам, если прошли предыдущие уроки конечно.
package net[paste][/paste]minecraft[paste][/paste]src;import java[paste][/paste]util[paste][/paste]*;import java[paste][/paste]util[paste][/paste]Map;public class mod_freeper extends BaseMod{ public String Version() { return "1[paste][/paste]7[paste][/paste]3"; }}Теперь в класс mod_freeper вставляем следующий код:
public mod_freeper() { ModLoader[paste][/paste]RegisterEntityID(EntityFreeper[paste][/paste]class, "Freeper", ModLoader[paste][/paste]getUniqueEntityId()); ModLoader[paste][/paste]AddSpawn(EntityFreeper[paste][/paste]class, 500, EnumCreatureType[paste][/paste]creature); }
Регестрируем моба в нашем мире:
ModLoader[paste][/paste]AddSpawn(EntityFreeper[paste][/paste]class, 500, EnumCreatureType[paste][/paste]creature);Спавн моба. Число 500 обозначает их редкость:
ModLoader[paste][/paste]AddSpawn(EntityFreeper[paste][/paste]class, 500, EnumCreatureType[paste][/paste]creature);Размер тени мы сможем указать ври помощи этого кода:
public void AddRenderer(Map map) { map[paste][/paste]put(EntityFreeper[paste][/paste]class, new RenderFreeper(new ModelFreeper(), 1[paste][/paste]0F)); }Далее.
Создаем файл под названием EntityFreeper.java.
Вписываем туда этот код:
package net[paste][/paste]minecraft[paste][/paste]src;Создаем класс EntityFreeper с указанием, что это нейтральный моб (животное).
public class EntityFreeper extends EntityAnimalВписываем в класс EntityFreeper следующий код:
public EntityFreeper(World world) { super(world); texture = "/mob/freeper[paste][/paste]png"; setSize(1[paste][/paste]5F, 1[paste][/paste]5F); }Тут мы объясняем мобу, что мир, в котором он будет жить, супер:
super(world);Тут мы указываем путь к текстуре:
texture = "/mob/freeper[paste][/paste]png";http://savepic.ru/2994155.htm
(размеры не изменять!)
Тут размеры коллайдера на мобе:
setSize(1F, 1F);Это просто скопируйте. Тут записываются и считываются данные.
public void writeEntityToNBT(NBTTagCompound nbttagcompound) { super[paste][/paste]writeEntityToNBT(nbttagcompound); } public void readEntityFromNBT(NBTTagCompound nbttagcompound) { super[paste][/paste]readEntityFromNBT(nbttagcompound); }Теперь мы указываем звуки, которые он будет издавать.
Это отвечает за то, что он будет издавать постоянно. В моем случае он будет кукарекать.
protected String getLivingSound(){ return "mob[paste][/paste]chicken"; }Это отвечает за то, что он будет издавать при уменьшении HP.
protected String getHurtSound() { return "mob[paste][/paste]creeper"; }Это отвечает за то, что он будет издавать при смерти.
protected String getDeathSound() { return "mob[paste][/paste]creeperdeath"; }Устанавливаем громкость.
protected float getSoundVolume() { return 0[paste][/paste]4F; }Вписываем ID предмета, который выпадет после смерти моба.
protected int getDropItemId() { return 289; }Проверяем.
http://savepic.net/1838545.htm
Идем далее.
Назвав файл RenderFreeper.java, мы вписываем в него следующий код:
package net[paste][/paste]minecraft[paste][/paste]src;public class RenderFreeper extends RenderLiving{ public RenderFreeper(ModelBase modelbase, float f) { super(modelbase, f); } public void func_177_a(EntityFreeper ebs, double d, double d1, double d2, float f, float f1) { super[paste][/paste]doRenderLiving(ebs, d, d1, d2, f, f1); } public void doRenderLiving(EntityLiving entityliving, double d, double d1, double d2, float f, float f1) { func_177_a((EntityFreeper)entityliving, d, d1, d2, f, f1); } public void doRender(Entity entity, double d, double d1, double d2, float f, float f1) { func_177_a((EntityFreeper)entity, d, d1, d2, f, f1); }}Собственно это он генерирует нашего моба в мире (отображает). Думаю и вам, и мне будет легче, если вы просто скопируете его к себе.
Начинаем, как всегда с того, что создаем файл и даем ему имя. В данном случае, имя ему будет ModelFreeper.java.
Ну и, наконец, самое главное... модель нашего моба. Чтобы делать модели для minecraft'a, нужна специальная программа, она называется Techne. Впоследствии, возможно мы и напишем пару уроков по “созданию” модели в этой программе. Но пока, скопируйте просто готовый код фрипера. Объяснять тут ничего не надо, так как программа сама все вам сгенерирует.
package net[paste][/paste]minecraft[paste][/paste]src;public class ModelFreeper extends ModelBase{ public ModelFreeper() { this(0[paste][/paste]0F); } public ModelFreeper(float f) { int i = 4; head = new ModelRenderer(0, 0); head[paste][/paste]addBox(-4F, -8F, -4F, 8, 8, 8, f); head[paste][/paste]setRotationPoint(0[paste][/paste]0F, i, 0[paste][/paste]0F); field_1270_b = new ModelRenderer(32, 0); field_1270_b[paste][/paste]addBox(-4F, -8F, -4F, 8, 8, 8, f + 0[paste][/paste]5F); field_1270_b[paste][/paste]setRotationPoint(0[paste][/paste]0F, i, 0[paste][/paste]0F); body = new ModelRenderer(16, 16); body[paste][/paste]addBox(-4F, 0[paste][/paste]0F, -2F, 8, 12, 4, f); body[paste][/paste]setRotationPoint(0[paste][/paste]0F, i, 0[paste][/paste]0F); leg1 = new ModelRenderer(0, 16); leg1[paste][/paste]addBox(-2F, 0[paste][/paste]0F, -2F, 4, 6, 4, f); leg1[paste][/paste]setRotationPoint(-2F, 12 + i, 4F); leg2 = new ModelRenderer(0, 16); leg2[paste][/paste]addBox(-2F, 0[paste][/paste]0F, -2F, 4, 6, 4, f); leg2[paste][/paste]setRotationPoint(2[paste][/paste]0F, 12 + i, 4F); leg3 = new ModelRenderer(0, 16); leg3[paste][/paste]addBox(-2F, 0[paste][/paste]0F, -2F, 4, 6, 4, f); leg3[paste][/paste]setRotationPoint(-2F, 12 + i, -4F); leg4 = new ModelRenderer(0, 16); leg4[paste][/paste]addBox(-2F, 0[paste][/paste]0F, -2F, 4, 6, 4, f); leg4[paste][/paste]setRotationPoint(2[paste][/paste]0F, 12 + i, -4F); } public void render(float f, float f1, float f2, float f3, float f4, float f5) { setRotationAngles(f, f1, f2, f3, f4, f5); head[paste][/paste]render(f5); body[paste][/paste]render(f5); leg1[paste][/paste]render(f5); leg2[paste][/paste]render(f5); leg3[paste][/paste]render(f5); leg4[paste][/paste]render(f5); } public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5) { head[paste][/paste]rotateAngleY = f3 / 57[paste][/paste]29578F; head[paste][/paste]rotateAngleX = f4 / 57[paste][/paste]29578F; leg1[paste][/paste]rotateAngleX = MathHelper[paste][/paste]cos(f * 0[paste][/paste]6662F) * 1[paste][/paste]4F * f1; leg2[paste][/paste]rotateAngleX = MathHelper[paste][/paste]cos(f * 0[paste][/paste]6662F + 3[paste][/paste]141593F) * 1[paste][/paste]4F * f1; leg3[paste][/paste]rotateAngleX = MathHelper[paste][/paste]cos(f * 0[paste][/paste]6662F + 3[paste][/paste]141593F) * 1[paste][/paste]4F * f1; leg4[paste][/paste]rotateAngleX = MathHelper[paste][/paste]cos(f * 0[paste][/paste]6662F) * 1[paste][/paste]4F * f1; } public ModelRenderer head; public ModelRenderer field_1270_b; public ModelRenderer body; public ModelRenderer leg1; public ModelRenderer leg2; public ModelRenderer leg3; public ModelRenderer leg4;}Скриншот из игры:
http://savepic.ru/2997227.htm
От FunnyAlien: Мобы имеют АИ как у обычной свиньи. Бегают, прыгают, улыбаются. Чуть позже мы вместе с Максимом расскажем как сделать вражеского моба и дружелюбного по типу Волка.
От Aswo: Всем привет, я Максим. С сегодняшнего дня я присоединяюсь к Вале, дабы помочь ему и вам в этом нелегком деле. Так же думаю, будет серия уроков по Techne, в которых вы научитесь моделировать объекты для игры. Ну и конечно же добавлять их в игру. В общем, зубрите пока первые девять глав Нотч
Глава 10. Создание нового враждебного моба - Advanced.
Ожидайте.
Глава 11. Создание разностороннего блока.
Копируем данный код, он должен уже быть ясен вам. Если нет, то бегом зубрить предыдущие главы.
Cоздаем файл с именем mod_tex.java дабы не портить mod_gcc и не запутаться.
package net[paste][/paste]minecraft[paste][/paste]src;import java[paste][/paste]util[paste][/paste]Random;public class mod_tex extends BaseMod{ public static Block Tex = new BlockTex(110, 0)[paste][/paste]setHardness(1[paste][/paste]0F)[paste][/paste]setResistance(6000[paste][/paste]0F)[paste][/paste]setBlockName("Tex");} public String Version() { return "1[paste][/paste]7_03"; } public mod_tex() { ModLoader[paste][/paste]RegisterBlock(Tex); Tex[paste][/paste]blockIndexInTexture = ModLoader[paste][/paste]addOverride("/terrain[paste][/paste]png", "/textures/Tex[paste][/paste]png"); ModLoader[paste][/paste]AddName(Tex, "Tex"); ModLoader[paste][/paste]AddRecipe(new ItemStack(Tex, 1), new Object[]{ "#", Character[paste][/paste]valueOf('#'), Block[paste][/paste]dirt,}); }}
Далее пишем под публичной блока:
Публичная текстуры с бока:
public static int TexSide;Публичная текстуры с лица:
public static int TexFront;Сделали? Отлично! Теперь нам нужно указать TexSide и TexFront куда им ходить за текстурой. Пишем после рецепта:
Путь к текстуре, которя будет боковой:
TexSide = ModLoader[paste][/paste]addOverride("/terrain[paste][/paste]png", "/textures/TexSide[paste][/paste]png");Путь к текстуре, которя будет лицевой:
TexFront = ModLoader[paste][/paste]addOverride("/terrain[paste][/paste]png", "/textures/TexFront[paste][/paste]png");Front.
http://savepic.ru/2985844.htm
Side.
http://savepic.net/1891524.htm
Обычная Tex.
http://savepic.net/1837253.htm
Проверяем.
http://savepic.ru/3004276.htm
Двинемся далее. Cоздаем файл с именем BlockTex.java.
Вот код для отображении текстуры на нашем блоке. Думаю, что потом вам не составит труда отредактировать его для своего следующего блока. В общих словах, вся эта махина создает блок с текстурой Tex. Потом присваивает всем сторонам текстуру TexSide, а уже потом только лицевой стороне присваивается текстура TexFront.
package net[paste][/paste]minecraft[paste][/paste]src;import java[paste][/paste]util[paste][/paste]Random;public class BlockTex extends Block{ public BlockTex(int i, int j) { super(i, j, Material[paste][/paste]rock); blockIndexInTexture = j; } public int idDropped(int i, int j) { return mod_tex[paste][/paste]Tex[paste][/paste]blockID; } public int quantityDropped(Random random) { return 2; } public int getBlockTextureFromSideAndMetadata(int i, int j) { if(i == 1) { return blockIndexInTexture; } if(i == 0) { return blockIndexInTexture; } int k = mod_tex[paste][/paste]TexFront; if(j == 2 && i == 2) { return k; } if(j == 3 && i == 5) { return k; } if(j == 0 && i == 3) { return k; } if(j == 1 && i == 4) { return k; } else { return mod_tex[paste][/paste]TexSide; } } public int getBlockTextureFromSide(int i) { if(i == 1) { return blockIndexInTexture; } if(i == 0) { return blockIndexInTexture; } if(i == 3) { return mod_tex[paste][/paste]TexFront; } else { return mod_tex[paste][/paste]TexSide; } }Ну и как бы бонус Вот эти пару строчек будут ставить блок к вам лицом. Если это нужно, то впишите их в конце.
public void onBlockPlacedBy(World world, int i, int j, int k, EntityLiving entityliving) { int l = MathHelper[paste][/paste]floor_double((double)((entityliving[paste][/paste]rotationYaw * 4F) / 360F) + 2[paste][/paste]5D) & 3; world[paste][/paste]setBlockMetadataWithNotify(i, j, k, l); }Скриншот из игры:
http://savepic.net/1840316.htm
Глава 12. Создание нового моба-помощника. Лучник - Advanced.
Эта статья рассчитана на продвинутых пользователей умеющих делать простейшие моды для майнкрафта, и здесь я попытаюсь рассказать о том как сделать моба который будет вас защищать стоя на месте.
Итак начнем:
Создаем файл mod_BowMan.java в котором мы укажем блок спавна нашего защитника:
package net[paste][/paste]minecraft[paste][/paste]src;public class mod_BowMan extends BaseMod{public static final Block BowManEgg = (new BlockBowManEgg(164, 0))[paste][/paste]setHardness(0[paste][/paste]0F)[paste][/paste]setResistance(0[paste][/paste]0F)[paste][/paste]setBlockName("BowManegg"); public mod_BowMan() { ModLoader[paste][/paste]RegisterBlock(BowManEgg); ModLoader[paste][/paste]AddName(BowManEgg, "Bowman Egg"); BowManEgg[paste][/paste]blockIndexInTexture = ModLoader[paste][/paste]addOverride("/terrain[paste][/paste]png", "/textures/bowmanegg[paste][/paste]png"); ModLoader[paste][/paste]AddRecipe(new ItemStack(BowManEgg, 1), new Object[] { "X", Character[paste][/paste]valueOf('X'), Block[paste][/paste]dirt}); ModLoader[paste][/paste]RegisterEntityID(net[paste][/paste]minecraft[paste][/paste]src[paste][/paste]EntityBowMan[paste][/paste]class, "entityBowMan", ModLoader[paste][/paste]getUniqueEntityId()); } public String Version() { return "Guard Mob Tutorial by Perpetual Motion Team"; } }Теперь создаем файл EntityBowMan.java
Начало такое-же как и в создании нейтрала
package net[paste][/paste]minecraft[paste][/paste]src;import java[paste][/paste]util[paste][/paste]List;import java[paste][/paste]util[paste][/paste]Random;public class EntityBowMan extends EntityAnimal{ public EntityBowMan(World world) { super(world); texture = "/mob/char[paste][/paste]png"; moveSpeed = 0[paste][/paste]0F; health = 50; isImmuneToFire = true; }Но появляется пара новых строчек.
Скорость передвижения моба(0.7F - скорость игрока, 0.0F - моб стоит на месте), у нас будет лучник, поэтому скорость 0.
moveSpeed = 0[paste][/paste]0F;Жизни моба(1 жизнь - пол-сердца, у игрока 20 жизней).
health = 50;Иммунитет к огню (и к лаве ).
isImmuneToFire = true;Теперь дописываем дальше:
Чтоб наш моб не пропадал.
protected boolean canDespawn() { return false; }Теперь надо чтоб лучник находил врагов:
Здесь в каждую переменную типа list записывается данный о враждебных мобах.
protected void updatePlayerActionState() { if(playerToAttack == null) { List list; list = worldObj[paste][/paste]getEntitiesWithinAABB(net[paste][/paste]minecraft[paste][/paste]src[paste][/paste]EntityMob[paste][/paste]class, AxisAlignedBB[paste][/paste]getBoundingBoxFromPool(posX - 16[paste][/paste]0D, posY - 4[paste][/paste]0D, posZ - 16[paste][/paste]0D, posX + 17[paste][/paste]0D, posY + 5[paste][/paste]0D, posZ + 17[paste][/paste]0D)); if(list[paste][/paste]isEmpty()) { list = worldObj[paste][/paste]getEntitiesWithinAABB(net[paste][/paste]minecraft[paste][/paste]src[paste][/paste]EntityMob[paste][/paste]class, AxisAlignedBB[paste][/paste]getBoundingBoxFromPool(posX - 16[paste][/paste]0D, posY - 12[paste][/paste]0D, posZ - 16[paste][/paste]0D, posX + 17[paste][/paste]0D, posY - 4[paste][/paste]0D, posZ + 17[paste][/paste]0D)); if(list[paste][/paste]isEmpty()) { list = worldObj[paste][/paste]getEntitiesWithinAABB(net[paste][/paste]minecraft[paste][/paste]src[paste][/paste]EntityMob[paste][/paste]class, AxisAlignedBB[paste][/paste]getBoundingBoxFromPool(posX - 16[paste][/paste]0D, posY - 20[paste][/paste]0D, posZ - 16[paste][/paste]0D, posX + 17[paste][/paste]0D, posY - 12[paste][/paste]0D, posZ + 17[paste][/paste]0D)); } } if(!list[paste][/paste]isEmpty()) { setTarget((Entity)list[paste][/paste]get(worldObj[paste][/paste]rand[paste][/paste]nextInt(list[paste][/paste]size()))); } } super[paste][/paste]updatePlayerActionState(); }Теперь обрабатываем событие на атаку:
protected void attackEntity(Entity entity, float f) { if(f < 240F) { double d = entity[paste][/paste]posX - posX; double d1 = entity[paste][/paste]posZ - posZ; if(attackTime == 0) { EntityArrow entityarrow = new EntityArrow(worldObj, this); entityarrow[paste][/paste]posY += 0[paste][/paste]1999999761581421D; double d2 = (entity[paste][/paste]posY + (double)entity[paste][/paste]getEyeHeight()) - 0[paste][/paste]20000000298023224D - entityarrow[paste][/paste]posY; float f1 = MathHelper[paste][/paste]sqrt_double(d * d + d1 * d1) * 0[paste][/paste]2F; worldObj[paste][/paste]playSoundAtEntity(this, "random[paste][/paste]bow", 1[paste][/paste]0F, 1[paste][/paste]0F / (rand[paste][/paste]nextFloat() * 0[paste][/paste]4F + 0[paste][/paste]8F)); worldObj[paste][/paste]entityJoinedWorld(entityarrow); entityarrow[paste][/paste]setArrowHeading(d, d2 + (double)f1, d1, 1[paste][/paste]5F, 12F); attackTime = 2; } rotationYaw = (float)((Math[paste][/paste]atan2(d1, d) * 180D) / 3[paste][/paste]1415927410125732D) - 90F; hasAttacked = true; } }Если умеете нормально программировать, то можете поменять здесь код на свою обработку.
А так объясню только 1 переменную:
Время до следующей атаки (у скелета время = 30, а у нас в 15 раз быстрее )
attackTime = 2;И наконец дописываем концовку:
protected String getLivingSound() { return "mob[paste][/paste]skeleton"; } protected String getHurtSound() { return "mob[paste][/paste]skeletonhurt"; } protected String getDeathSound() { return "mob[paste][/paste]skeletondeath"; } private int angerLevel; private int randomSoundDelay;}Теперь нам надо сделать файл BlockBowManEgg.java:
package net[paste][/paste]minecraft[paste][/paste]src;import java[paste][/paste]io[paste][/paste]PrintStream;import java[paste][/paste]util[paste][/paste]Random;public class BlockBowManEgg extends Block{ protected BlockBowManEgg(int i, int j) { super(i, j, Material[paste][/paste]ground); } public int quantityDropped(Random random) { return 1; } public int tickRate() { return 30; } public void onBlockClicked(World world, int i, int j, int k, EntityPlayer entityplayer) { double d = i; double d1 = j; double d2 = k; EntityBowMan entitybowman = new EntityBowMan(world); entitybowman[paste][/paste]setLocationAndAngles(d, d1, d2, world[paste][/paste]rand[paste][/paste]nextFloat() * 360F, 0[paste][/paste]0F); world[paste][/paste]entityJoinedWorld(entitybowman); }}Здесь все просто - по нажатию левой кнопкой мыши блок ломается (потому-что крепкость 0) и вызывает на это место лучника.
Остались только текстуры:
Текстура лучника - не требуется (в коде вписана стандартная текстура игрока).
Текстура bowmanegg.png - берем любой файл 16*16 и кидаем в папку textures в minecraft.jar с именем bowmanegg.png.
Ну вот стрелок и готов.
Автор 12 главы: DarkMan.
Мини-глава. Нормальное стекло.
Многие встречались с проблемой, когда после создания "прозрачной" текстуры, через блок можно было смотреть через весь мир, типа X-Ray мода.
Данная проблема решается строчками, которые добавляются в .java блока.
public boolean isOpaqueCube() { return false; } public boolean shouldSideBeRendered(IBlockAccess iblockaccess, int i, int j, int k, int l) { int i1 = iblockaccess[paste][/paste]getBlockId(i, j, k); if(!localFlag && i1 == blockID) { return false; } else { return super[paste][/paste]shouldSideBeRendered(iblockaccess, i, j, k, l); } } private boolean localFlag;Вот и все. После чего у вас будет красивое подобие стекла.
Удачи!
Глава 13. Создание новой брони на основе стандартных материалов.
Добавим к пабликам следующее и разберем:
public static Item titanHelmet = new ItemArmor(3003, 3, ModLoader[paste][/paste]AddArmor("titan"), 0)[paste][/paste]setItemName("titanHelmet");Название.
Item titanHelmetID.
20030 = кожа, 1 = золото и кольчуга, 2 = железо, 3 = алмаз.
В нашем случае алмаз.
3Вот тут самое интересное. Для вашей брони придется подписывать везде вот так, т.к это получается целый набор.
ModLoader[paste][/paste]AddArmor("titan")0 = шлем, 1 = нагрудник, 2 = штанишки, 3 = ботинки.
В нашем случае шлем.
0Опять повторяем название.
"titanHelmet"Сначала делаем текстуры для инвентаря.
Все как обычно. Текстура должна быть 16x16.
titanHelmet[paste][/paste]iconIndex = ModLoader[paste][/paste]addOverride("/gui/items[paste][/paste]png", "/textures/helmet[paste][/paste]png");Для красоты я взял текстуру железного шлема и затемнил.
http://savepic.org/2211241.htm
(размеры не изменять!)
Ну и теперь нам нужно добавить текстуру для самой брони на игроке.
Заходим в RenderPlayer.java и крутим в самый конец до строки:
"cloth", "chain", "iron", "diamond", "gold"Добавим наш титан:
"cloth", "chain", "iron", "diamond", "gold", "titan"И кинем текстуры снизу в minecraft.jar/armor.
Первая текстура. Обязательно назовите ее titan_1 - т.к префикс "titan".
http://savepic.ru/3041936.htm
(размеры не изменять!)
Вторая текстура. Название - titan_2.
http://savepic.org/2168233.htm
(размеры не изменять!)
Игровые названия делаются не для всего набора брони, а отдельно для каждого предмета из набора (например шлем).
Ну и рецепт так же.
Теперь осталось добавить остальную броню и протестировать.
Удачи!
Глава 14. Использование редстоуна с блоками. Часть 1.
Вот и долгожданная глава, уважаемые читатели!
Тут все на первый взгляд тяжело, но уверяю вас - все очень легко Нотч
Сейчас мы сделаем почти обычный TNT. При подключении редстоуна к блоку - он взорвется.
Откроем наш файлик BlockNew.java и добавим ниже строку:
public void onPoweredBlockChange(World world, int i, int j, int k, boolean flag) { if(world[paste][/paste]multiplayerWorld) { return; } else { float f = 5F; world[paste][/paste]createExplosion(null, i, j, k, f); return; } }Данной строкой мы проверяем, если блок активирован, то:
Устанавливаем силу взрыва.
float f = 5F;Создается взрыв.
world[paste][/paste]createExplosion(null, i, j, k, f);Ну и добавляем настройки связывания редстоуна:
public void onNeighborBlockChange(World world, int i, int j, int k, int l) { int i1 = world[paste][/paste]getBlockMetadata(i, j, k); if((i1 & 8) != 0) { if(world[paste][/paste]getBlockId(i, j - 1, k) != blockID) { world[paste][/paste]setBlockWithNotify(i, j, k, 0); } if(l > 0 && Block[paste][/paste]blocksList[l][paste][/paste]canProvidePower()) { onNeighborBlockChange(world, i, j - 1, k, l); } } else { boolean flag = false; if(world[paste][/paste]getBlockId(i, j + 1, k) != blockID) { world[paste][/paste]setBlockWithNotify(i, j, k, 0); flag = true; } if(!world[paste][/paste]isBlockNormalCube(i, j - 1, k)) { world[paste][/paste]setBlockWithNotify(i, j, k, 0); flag = true; if(world[paste][/paste]getBlockId(i, j + 1, k) == blockID) { world[paste][/paste]setBlockWithNotify(i, j + 1, k, 0); } } if(flag) { if(!world[paste][/paste]multiplayerWorld) { dropBlockAsItem(world, i, j, k, i1); } } else if(l > 0 && Block[paste][/paste]blocksList[l][paste][/paste]canProvidePower()) { boolean flag1 = world[paste][/paste]isBlockIndirectlyGettingPowered(i, j, k) || world[paste][/paste]isBlockIndirectlyGettingPowered(i, j + 1, k); onPoweredBlockChange(world, i, j, k, flag1); } } }Тут ничего менять не надо - все уже готовое.
Вот и все. Осталось только проверить
Экспериментировать можно всегда - сделайте так, чтобы блок не взрывался, а менял свои свойства, прыгал, двигался и прочее. Все действия подглядеть всегда можно в Block.java.
Первая часть главы закончена - я рассказал все самые основы. Чуть позже будет больше
Глава 15. Как создать свою музыкальную пластинку.
В уроке объяснения происходят в самом коде.
Создадим новый mod_musicdiscs.java:
package net[paste][/paste]minecraft[paste][/paste]src;import java[paste][/paste]util[paste][/paste]Random;public class mod_musicdiscs extends BaseMod{ public static final Item discExample = new ItemRecord(3005, "Example")[paste][/paste]setItemName("discExample"); // Обозначаем, что он ItemRecord (ID, "Имя звукового файла") public static final Item discExample2 = new ItemRecord(3006, "Example2")[paste][/paste]setItemName("discExample2"); public mod_musicdiscs(){ discExample[paste][/paste]iconIndex = ModLoader[paste][/paste]addOverride("/gui/items[paste][/paste]png", "/texututes/discExample[paste][/paste]png"); // Путь к png изображению discExample2[paste][/paste]iconIndex = ModLoader[paste][/paste]addOverride("/gui/items[paste][/paste]png", "/texututes/discExample2[paste][/paste]png"); ModLoader[paste][/paste]AddName(discExample, "Music Disc 1"); ModLoader[paste][/paste]AddName(discExample2, "Music Disc 2"); ModLoader[paste][/paste]AddRecipe(new ItemStack(mod_musicdiscs[paste][/paste]discExample, 1), new Object[] { "X", "#", Character[paste][/paste]valueOf('#'), Block[paste][/paste]obsidian, Character[paste][/paste]valueOf('X'), Block[paste][/paste]sand }); ModLoader[paste][/paste]AddRecipe(new ItemStack(mod_musicdiscs[paste][/paste]discExample2, 1), new Object[] { "X", "#", Character[paste][/paste]valueOf('#'), Block[paste][/paste]obsidian, Character[paste][/paste]valueOf('X'), Block[paste][/paste]dirt });} public String Version() { return "Tutorial by Sawoder"; }}Теперь просто кидаем в указанный вами путь .png изображение своего музыкального диска.
А музыку в папку resources\streaming в формате .ogg и с названием Example и Example2.
Глава 16. Как создать специальный файл настроек мода.
В уроке объяснения происходят в самом коде.
Начнем. Наш блок будет иметь имя firstBlock.
Впишите в mod_prop следующее:
package net[paste][/paste]minecraft[paste][/paste]src;import java[paste][/paste]util[paste][/paste]Properties;import net[paste][/paste]minecraft[paste][/paste]client[paste][/paste]Minecraft;public class mod_prop extends BaseMod{ public mod_prop() { Properties properties = new Properties(); try { File file = new File((new StringBuilder())[paste][/paste]append(Minecraft[paste][/paste]getMinecraftDir())[paste][/paste]append("/mods/mod_prop[paste][/paste]properties")[paste][/paste]toString()); // Создание нового файла пропорций, указываем путь и имя boolean flag = file[paste][/paste]createNewFile(); if(flag) { FileOutputStream fileoutputstream = new FileOutputStream(file); properties[paste][/paste]setProperty("firstBlockID", Integer[paste][/paste]toString(129)); // Первое название, второе ID (129)[paste][/paste] Важно! ID писать обязательно! properties[paste][/paste]store(fileoutputstream, "Change the ID's[paste][/paste]"); // Сообщения в пропорциях fileoutputstream[paste][/paste]close(); } properties[paste][/paste]load(new FileInputStream((new StringBuilder())[paste][/paste]append(Minecraft[paste][/paste]getMinecraftDir())[paste][/paste]append("/mods/mod_prop[paste][/paste]properties")[paste][/paste]toString())); firstBlockID = Integer[paste][/paste]parseInt(properties[paste][/paste]getProperty("firstBlockID")); // Интегрирует блок в пропорции } catch(IOException ioexception) { ioexception[paste][/paste]printStackTrace(); } firstBlock = new BlockFirstBlock(firstBlockID, ModLoader[paste][/paste]addOverride("/terrain[paste][/paste]png", "/textures/firstBlock[paste][/paste]png"))[paste][/paste]setHardness(0[paste][/paste]2F)[paste][/paste]setResistance(1[paste][/paste]5F)[paste][/paste]setLightValue(1[paste][/paste]0F)[paste][/paste]setStepSound(Block[paste][/paste]soundGrassFootstep)[paste][/paste]setBlockName("firstBlock"); // Чуть изменено ModLoader[paste][/paste]RegisterBlock(firstBlock); ModLoader[paste][/paste]AddName(firstBlock, "Properties Test"); ModLoader[paste][/paste]AddRecipe(new ItemStack(firstBlock, 4), new Object[] { "XX ", "XX ", Character[paste][/paste]valueOf('X'), Block[paste][/paste]dirt }); } public static Block firstBlock; public static int firstBlockID; // Регестрируем блок отображения в пропорциях public String Version() { return "Tutorial by Sawoder"; }}Вот и все, теперь с помощью файла mod_prop.properties в папке mods можно редактировать блок!
У нашей команды есть своя официальная конференция в джаббере.
Там можно задать вопросы по моддингу - и получить быстрый ответ, поговорить с разработчиками учебника или просто пофлудить
Сервер - conference.jabber.ru
Комната - mc-guide
Регистрировать аккуант на jabber.ru, а качать лучшего всего клиент Psi.
Но сидеть в конфе можно и через квип.
Всем спасибки за внимание!
Учебник разрабатывается коллективом mc.salmons.ru!