- Регистрация
- 4 Апр 2025
- Сообщения
- 24
- Реакции
- 0
- Баллы
- 1
- Город
- Санкт-Петербург
- Веб-сайт
- paxgame.ru
- Discord
- nicolayka
Я всё же решился начать писать уроки без использования сторонних модов типо ModLoader и Forge.
Данный туториал пишется для клиента версии 1.3.2.
Для начала разберёмся, как всё же начать моддить. Для этого вам потребуется:
MCP | Minecraft | ModLoader
7.2 | 1.3.2 | 1.3.2
7.0a | 1.3.1 | 1.3.1
6.2 | 1.2.5 | 1.2.5
6.1 | 1.2.4 | 1.2.4
6.0 | 1.2.3 | 1.2.3
5.6 | 1.1.1 | 1.0
5.4 | 1.0.0 | 1.0
Установка:
2. Создание нового рецепта крафта (добыча блока/предмета) (1.3.2)
3. Добавление блока в лист креативного режима (только для 1.2.5)
4. Добавление блока в генерацию мира (1.3.2)
5. Добавление имени блоку (1.3.2)
6. Добавление своего файла крафтинга (1.3.2)
7. Создание своего растения
8. Создание моба (враждебный и дружелюбный) (1.3.2)
9. Создание своего биома (1.3.2)
10. Создание инструментов
11. Создание брони на основе новых материалов
12. Создание еды (с эффектами) (1.3.2)
13. Создание достижений
14. Создание рецепта для печки (1.3.2)
15. Делаем предмет топливом для печки (1.3.2)
16. Добавляем новый (свой) игровой режим (1.3.2)
17. Создание своей (новой) жидкости (1.3.2) (Добавлено)
Дополнения для блоков (Обновлено) (1.3.2)
Создание второго items.png (1.3.2)
Создание второго terrain.png (1.3.2) (доделано не до конца)
Получаем любую версию MineCraft
Знакомо? правильно - 2 - клиент, остальное - сервер.
Также мы видим метаинфу - размер и хэш файла.
4. Скачиваем нужную версию
Допустим возьмём клиент версии 1.4.7: дописываем к ссылке сайта
Ну и напоследок:
скажу что на сайте есть и другие "вкусности" например pe версия, а также файлы личного пользования(немногие, правда, запаролены).
Коды все рабочие и протестированные!
Отдельное спасибо:
P.S Тема будет пополняться со временем, так как я сначала делаю, потом выкладываю.
Не забываем удалить папку!
META-INFиз minecraft.jar
Если не удалите её, то будет много ошибок!
Важно!
"Большинство модов после этого изменения клиента (сервера) работать уже не будет"
и
"Если обновите клиент, то ваши модификации удалятся"
Автор - я. Копирование без размещения ссылки - запрещено.
Данный туториал пишется для клиента версии 1.3.2.
Для начала разберёмся, как всё же начать моддить. Для этого вам потребуется:
- Java Development Kit 6 (JDK 6) или Java Development 7 (JDK 7)
- Оригинальный minecraft.jar(папка bin) и minecraft_server.jar
- Notepad ++, Eclipse(лучше конечно использовать Eclipse)
- Minecraft Coder Pack (нужную вам версию можно посмотреть ниже)
MCP | Minecraft | ModLoader
7.2 | 1.3.2 | 1.3.2
7.0a | 1.3.1 | 1.3.1
6.2 | 1.2.5 | 1.2.5
6.1 | 1.2.4 | 1.2.4
6.0 | 1.2.3 | 1.2.3
5.6 | 1.1.1 | 1.0
5.4 | 1.0.0 | 1.0
Установка:
- Создайте папку в любом удобном для вас месте, желательно, что бы в пути небыло русских символов
- Скопируйте содержимое архива mcp в эту папку
- Скопируйте папку bin (из клиента) и minecraft_server.jar в папку jars
- Откройте minecraft.jar с помощью архиватора, и удалите папку META-INF (если такая имеется)
- Пропишите путь к javac.exe в системной переменной PATH
- Пример строки смотрите ниже (не забудьте : перед строчкой)
;C:\Program Files\Java\jdk1.7.0_07\bin
- Если же у вас установлена другая версия JAVA, то сначала посмотрите путь в папке ProgramFiles, а потом измените в строке
- Зайдите в Eclipse, при первом входе он вас попросит указать путь к новому проекту. Укажите путь до папки eclipse в новой папке
- Закройте Eclipse
- Запустите decompile.bat
- Как только декомпиляция закончится, открывайте Eclipse и кодьте =)
1. Вам нужно создать новый файл под именем BlockNew.java в папке src.
2. Вот пример:
package net.minecraft.src;
import java.util.Random;
public class BlockNew extends Block
{
public BlockNew(int par1, int par2)
{
super(par1, par2, Material.rock);
this.setCreativeTab(CreativeTabs.tabBlock);
}
/**
* Returns the ID of the items to drop on destruction.
*/
public int idDropped(int par1, Random par2Random, int par3)
{
return Block.newBlock.blockID;
}
}
Список категорий для "креатива" (для добавления нашего блока в определённую закладку)
this.setCreativeTab(CreativeTabs.tabAllSearch); //Добавляет наш Block в категорию "Поиск" как и все предметы, блоки.
this.setCreativeTab(CreativeTabs.tabBlock); //Добавляет наш Block в категорию "Блоки" как Стекло, Земля, и т.д.
this.setCreativeTab(CreativeTabs.tabBrewing); //Добавляет наш Block в категорию "Зелья" как Зелья, Ингредиенты и т.д.
this.setCreativeTab(CreativeTabs.tabCombat); //Добавляет наш Block в категорию "Амуниция" как Броня, Мечи, и т.д.
this.setCreativeTab(CreativeTabs.tabDeco); //Добавляет наш Block в категорию "Декорации" как Цветки, Сундук, и т.д.
this.setCreativeTab(CreativeTabs.tabFood); //Добавляет наш Block в категорию "Еда" как Печеньки, Хлеб и т.д.
this.setCreativeTab(CreativeTabs.tabInventory); //Сюда не надо ничего не добавлять, если добавили Block, Item то они будут в иконке "Destroy Item".
this.setCreativeTab(CreativeTabs.tabMaterials); //Добавляет наш Block в категорию "Материалы" как Уголь, Сундук, и т.д.
this.setCreativeTab(CreativeTabs.tabMisc); //Добавляет наш Block в категорию "Разное" как Яйца мобов, Музыкальные диски, и т.д.
this.setCreativeTab(CreativeTabs.tabRedstone); //Добавляет наш Block в категорию "Редстоун" как Поршень, ТНТ, и т.д.
this.setCreativeTab(CreativeTabs.tabTools); //Добавляет наш Block в категорию "Инструменты" как Кирки, Компасс и т.д.
this.setCreativeTab(CreativeTabs.tabTransport); //Добавляет наш Block в категорию "Транспорт" как Вагонетка, Рульсы, и т.д.
3. Теперь нужно добавить ваш блок непосредственно в Block.java
Идём в конец файла и ищем
/**
* The index of the texture to be displayed for this block. May vary based on graphics settings. Mostly seems to
* come from terrain.png, and the index is 0-based (grass is 0).
*/
Над ним вставляем:
public static final Block newBlock = (new BlockNew(161, 8)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setBlockName("new").setRequiresSelfNotify();
Где:
161 - ID блока (свободные номера начинаются с 137)
8 - номер текстуры в terrain.png
setHardness(2.0F) - прочность ()
.setResistance(4F) - сопротивление
.setStepSound(soundGlassFootstep) - звук при разбиении
.setBlockName("new") - имя блока (для перевода через lang-файл)
.setLightValue(1.0F) - свечение блока
Если вы хотите сделать к примеру ступеньку, или же вертикальную палку, или паутину, то в файле BlockNew.java добавьте
public int getRenderType()
{
return 10;
}
Где 10 - TYPE (тип блока)
package net.minecraft.src;
import java.util.Random;
public class BlockNew extends Block
{
public BlockNew(int par1, int par2)
{
super(par1, par2, Material.rock);
this.setCreativeTab(CreativeTabs.tabBlock);
}
/**
* Returns the ID of the items to drop on destruction.
*/
public int idDropped(int par1, Random par2Random, int par3)
{
return Block.newBlock.blockID;
}
}
Список категорий для "креатива" (для добавления нашего блока в определённую закладку)
this.setCreativeTab(CreativeTabs.tabAllSearch); //Добавляет наш Block в категорию "Поиск" как и все предметы, блоки.
this.setCreativeTab(CreativeTabs.tabBlock); //Добавляет наш Block в категорию "Блоки" как Стекло, Земля, и т.д.
this.setCreativeTab(CreativeTabs.tabBrewing); //Добавляет наш Block в категорию "Зелья" как Зелья, Ингредиенты и т.д.
this.setCreativeTab(CreativeTabs.tabCombat); //Добавляет наш Block в категорию "Амуниция" как Броня, Мечи, и т.д.
this.setCreativeTab(CreativeTabs.tabDeco); //Добавляет наш Block в категорию "Декорации" как Цветки, Сундук, и т.д.
this.setCreativeTab(CreativeTabs.tabFood); //Добавляет наш Block в категорию "Еда" как Печеньки, Хлеб и т.д.
this.setCreativeTab(CreativeTabs.tabInventory); //Сюда не надо ничего не добавлять, если добавили Block, Item то они будут в иконке "Destroy Item".
this.setCreativeTab(CreativeTabs.tabMaterials); //Добавляет наш Block в категорию "Материалы" как Уголь, Сундук, и т.д.
this.setCreativeTab(CreativeTabs.tabMisc); //Добавляет наш Block в категорию "Разное" как Яйца мобов, Музыкальные диски, и т.д.
this.setCreativeTab(CreativeTabs.tabRedstone); //Добавляет наш Block в категорию "Редстоун" как Поршень, ТНТ, и т.д.
this.setCreativeTab(CreativeTabs.tabTools); //Добавляет наш Block в категорию "Инструменты" как Кирки, Компасс и т.д.
this.setCreativeTab(CreativeTabs.tabTransport); //Добавляет наш Block в категорию "Транспорт" как Вагонетка, Рульсы, и т.д.
3. Теперь нужно добавить ваш блок непосредственно в Block.java
Идём в конец файла и ищем
/**
* The index of the texture to be displayed for this block. May vary based on graphics settings. Mostly seems to
* come from terrain.png, and the index is 0-based (grass is 0).
*/
Над ним вставляем:
public static final Block newBlock = (new BlockNew(161, 8)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setBlockName("new").setRequiresSelfNotify();
Где:
161 - ID блока (свободные номера начинаются с 137)
8 - номер текстуры в terrain.png
setHardness(2.0F) - прочность ()
.setResistance(4F) - сопротивление
.setStepSound(soundGlassFootstep) - звук при разбиении
.setBlockName("new") - имя блока (для перевода через lang-файл)
.setLightValue(1.0F) - свечение блока
Если вы хотите сделать к примеру ступеньку, или же вертикальную палку, или паутину, то в файле BlockNew.java добавьте
public int getRenderType()
{
return 10;
}
Где 10 - TYPE (тип блока)
2. Создание нового рецепта крафта (добыча блока/предмета) (1.3.2)
1. Откройте CraftingManager.java
Ищем что-то похожее на:
this.addRecipe(new ItemStack(Block.enchantmentTable, 1), new Object[] {" B ", "D#D", "###", '#', Block.obsidian, 'B', Item.book, 'D', Item.diamond});
Добавляем после него рецепт для нашего только что созданного блока
this.addRecipe(new ItemStack(Block.new, 1), new Object[] {"###", "###", "###", '#', Block.dirt});
Где 1 - кол-во получаемого блока после крафта
# - в данном случае, все ячейки крафта заполняем землёй
Ищем что-то похожее на:
this.addRecipe(new ItemStack(Block.enchantmentTable, 1), new Object[] {" B ", "D#D", "###", '#', Block.obsidian, 'B', Item.book, 'D', Item.diamond});
Добавляем после него рецепт для нашего только что созданного блока
this.addRecipe(new ItemStack(Block.new, 1), new Object[] {"###", "###", "###", '#', Block.dirt});
Где 1 - кол-во получаемого блока после крафта
# - в данном случае, все ячейки крафта заполняем землёй
3. Добавление блока в лист креативного режима (только для 1.2.5)
Открываем файл ContainerCreative.java
В самом верху видим:
itemList = new ArrayList();
Block ablock[] =
{
Block.cobblestone, Block.stone, Block.oreDiamond, Block.oreGold, Block.oreIron, Block.oreCoal, Block.oreLapis, Block.oreRedstone, Block.stoneBrick, Block.stoneBrick,
Block.stoneBrick, Block.stoneBrick, Block.blockClay, Block.blockDiamond, Block.blockGold, Block.blockSteel, Block.bedrock, Block.blockLapis, Block.brick, Block.cobblestoneMossy,
Block.stairSingle, Block.stairSingle, Block.stairSingle, Block.stairSingle, Block.stairSingle, Block.stairSingle, Block.obsidian, Block.netherrack, Block.slowSand, Block.glowStone,
Block.wood, Block.wood, Block.wood, Block.wood, Block.leaves, Block.leaves, Block.leaves, Block.leaves, Block.dirt, Block.grass,
Block.sand, Block.sandStone, Block.sandStone, Block.sandStone, Block.gravel, Block.web, Block.planks, Block.planks, Block.planks, Block.planks,
Block.sapling, Block.sapling, Block.sapling, Block.sapling, Block.deadBush, Block.sponge, Block.ice, Block.blockSnow, Block.plantYellow, Block.plantRed,
Block.mushroomBrown, Block.mushroomRed, Block.cactus, Block.melon, Block.pumpkin, Block.pumpkinLantern, Block.vine, Block.fenceIron, Block.thinGlass, Block.netherBrick,
Block.netherFence, Block.stairsNetherBrick, Block.whiteStone, Block.mycelium, Block.waterlily, Block.tallGrass, Block.tallGrass, Block.chest, Block.workbench, Block.glass,
Block.tnt, Block.bookShelf, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth,
Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.dispenser, Block.stoneOvenIdle,
Block.music, Block.jukebox, Block.pistonStickyBase, Block.pistonBase, Block.fence, Block.fenceGate, Block.ladder, Block.rail, Block.railPowered, Block.railDetector,
Block.torchWood, Block.stairCompactPlanks, Block.stairCompactCobblestone, Block.stairsBrick, Block.stairsStoneBrickSmooth, Block.lever, Block.pressurePlateStone, Block.pressurePlatePlanks, Block.torchRedstoneActive, Block.button,
Block.trapdoor, Block.enchantmentTable, Block.redstoneLampIdle
};
И добавляем в этот список наш блок (или предмет)
, Block.new
В самом верху видим:
itemList = new ArrayList();
Block ablock[] =
{
Block.cobblestone, Block.stone, Block.oreDiamond, Block.oreGold, Block.oreIron, Block.oreCoal, Block.oreLapis, Block.oreRedstone, Block.stoneBrick, Block.stoneBrick,
Block.stoneBrick, Block.stoneBrick, Block.blockClay, Block.blockDiamond, Block.blockGold, Block.blockSteel, Block.bedrock, Block.blockLapis, Block.brick, Block.cobblestoneMossy,
Block.stairSingle, Block.stairSingle, Block.stairSingle, Block.stairSingle, Block.stairSingle, Block.stairSingle, Block.obsidian, Block.netherrack, Block.slowSand, Block.glowStone,
Block.wood, Block.wood, Block.wood, Block.wood, Block.leaves, Block.leaves, Block.leaves, Block.leaves, Block.dirt, Block.grass,
Block.sand, Block.sandStone, Block.sandStone, Block.sandStone, Block.gravel, Block.web, Block.planks, Block.planks, Block.planks, Block.planks,
Block.sapling, Block.sapling, Block.sapling, Block.sapling, Block.deadBush, Block.sponge, Block.ice, Block.blockSnow, Block.plantYellow, Block.plantRed,
Block.mushroomBrown, Block.mushroomRed, Block.cactus, Block.melon, Block.pumpkin, Block.pumpkinLantern, Block.vine, Block.fenceIron, Block.thinGlass, Block.netherBrick,
Block.netherFence, Block.stairsNetherBrick, Block.whiteStone, Block.mycelium, Block.waterlily, Block.tallGrass, Block.tallGrass, Block.chest, Block.workbench, Block.glass,
Block.tnt, Block.bookShelf, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth,
Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.cloth, Block.dispenser, Block.stoneOvenIdle,
Block.music, Block.jukebox, Block.pistonStickyBase, Block.pistonBase, Block.fence, Block.fenceGate, Block.ladder, Block.rail, Block.railPowered, Block.railDetector,
Block.torchWood, Block.stairCompactPlanks, Block.stairCompactCobblestone, Block.stairsBrick, Block.stairsStoneBrickSmooth, Block.lever, Block.pressurePlateStone, Block.pressurePlatePlanks, Block.torchRedstoneActive, Block.button,
Block.trapdoor, Block.enchantmentTable, Block.redstoneLampIdle
};
И добавляем в этот список наш блок (или предмет)
, Block.new
4. Добавление блока в генерацию мира (1.3.2)
1. Открываем файл BiomeDecorator.java
Ищем
protected WorldGenerator dirtGen;
Добавляем после
protected WorldGenerator newGen;
Ищем
dirtGen = new WorldGenMinable(Block.dirt.blockID, 32);
Добавляем после
newGen = new WorldGenMinable(Block.new.blockID, 2); //Кол-во блоков в одном месторождении
Идём в самый конец файла и ищем
this.genStandardOre1(20, this.dirtGen, 0, 128);
Вставляем после:
this.genStandardOre1(20, this.newGen, 0, 128);
Где 0 минимальная высота, а 128 - максимальная, до куда будет генерироваться блок. Т.е с нулевой высоты по 128 будет генерироваться наш блок
Ищем
protected WorldGenerator dirtGen;
Добавляем после
protected WorldGenerator newGen;
Ищем
dirtGen = new WorldGenMinable(Block.dirt.blockID, 32);
Добавляем после
newGen = new WorldGenMinable(Block.new.blockID, 2); //Кол-во блоков в одном месторождении
Идём в самый конец файла и ищем
this.genStandardOre1(20, this.dirtGen, 0, 128);
Вставляем после:
this.genStandardOre1(20, this.newGen, 0, 128);
Где 0 минимальная высота, а 128 - максимальная, до куда будет генерироваться блок. Т.е с нулевой высоты по 128 будет генерироваться наш блок
5. Добавление имени блоку (1.3.2)
Открываем minecraft.jar, папку lang и нужный файл языка. К примеру ru_RU.lang
Листаем ниже и находим такой код:
tile.waterlily.name=Кувшинка
tile.dragonEgg.name=Яйцо дракона
tile.redstoneLight.name=Лампа
И добавляем по аналогии наше название блока! В title.*** пишутся имена блоков!
tile.new.name=Новый блок
tile.new.name - имя блока, которое мы использовали тут (когда создавами сам блок):
Теперь припишем имя к предмету (внизу описан предмет - роза, ну для него и напишем имя)
Чуть ниже ищем строки:
item.shovelIron.name=Железная лопата
item.pickaxeIron.name=Железная кирка
item.hatchetIron.name=Железный топор
И добавляем по аналогии наше название предмета! В item.*** пишутся имена редметов!
item.rose.name=Колючая роза
item.rose.name - имя предмета, которое мы использовали при создании предмета (тут)
Как только напишу тутор как создать свой предмет - опишу присвоение имени.
Листаем ниже и находим такой код:
tile.waterlily.name=Кувшинка
tile.dragonEgg.name=Яйцо дракона
tile.redstoneLight.name=Лампа
И добавляем по аналогии наше название блока! В title.*** пишутся имена блоков!
tile.new.name=Новый блок
tile.new.name - имя блока, которое мы использовали тут (когда создавами сам блок):
.setBlockName("new").
Теперь припишем имя к предмету (внизу описан предмет - роза, ну для него и напишем имя)
Чуть ниже ищем строки:
item.shovelIron.name=Железная лопата
item.pickaxeIron.name=Железная кирка
item.hatchetIron.name=Железный топор
И добавляем по аналогии наше название предмета! В item.*** пишутся имена редметов!
item.rose.name=Колючая роза
item.rose.name - имя предмета, которое мы использовали при создании предмета (тут)
.setItemName("rose")
Как только напишу тутор как создать свой предмет - опишу присвоение имени.
6. Добавление своего файла крафтинга (1.3.2)
1. Открываем файл CraftingManager.java
Ищем
(new RecipesDyes()).addRecipes(this);
Добавляем после
(new RecipesMyRecipes()).addRecipes(this);
2. Создаём файл с таким же именем как указали выше - RecipesMyRecipes.java
3. Добавляем в файл следующие строки
package net.minecraft.src;
public class RecipesMyRecipes
{
public RecipesMyRecipes()
{
}
/**
* Adds the food recipes to the CraftingManager.
*/
public void addRecipes(CraftingManager CraftingManager)
{
par1CraftingManager.addRecipe(new ItemStack(Item.new, 6), new Object[] {"###", "###", "###", '#', Block.dirt});
}
}
Думаю, если вы читали уроки по созданию модов на ModLoader, там описывался крафтинг
Ищем
(new RecipesDyes()).addRecipes(this);
Добавляем после
(new RecipesMyRecipes()).addRecipes(this);
2. Создаём файл с таким же именем как указали выше - RecipesMyRecipes.java
3. Добавляем в файл следующие строки
package net.minecraft.src;
public class RecipesMyRecipes
{
public RecipesMyRecipes()
{
}
/**
* Adds the food recipes to the CraftingManager.
*/
public void addRecipes(CraftingManager CraftingManager)
{
par1CraftingManager.addRecipe(new ItemStack(Item.new, 6), new Object[] {"###", "###", "###", '#', Block.dirt});
}
}
Думаю, если вы читали уроки по созданию модов на ModLoader, там описывался крафтинг
7. Создание своего растения
1. Открываем файл Block.java
2. Добавляем новый блок как описано выше
Пример
roseblock = new BlockRose(162, 168).setHardness(0.5F).setResistance(0.3F).setLightValue(0F).setBlockName("rose");
3. Создаём файл с названием BlockRose (в нашем случае)
4. Добавляем в файл следующие строки
package net.minecraft.src;
import java.util.Random;
public class BlockRose extends Block
{
protected BlockRose(int par1, int par2)
{
super(par1, Material.plants);//материал растение
blockIndexInTexture = par2;
float f = 0.375F;
setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 1.0F, 0.5F + f);
setTickRandomly(true);
}
/**
* Ticks the block if it's been scheduled
*/
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)//Это сам алгоритм роста.
{
if (par1World.isAirBlock(par2, par3 + 1, par4))
{
int i;
for (i = 1; par1World.getBlockId(par2, par3 - i, par4) == blockID; i++) { }
if (i < 5) //Вырастает до 4-х блоков (если хотим, что бы рост был до 5-ти, то пишем число 6, всегда на единицу БОЛЬШЕ)
{
int j = par1World.getBlockMetadata(par2, par3, par4);
if (j == 15) //скорость роста (чем меньше значение, тем быстрее ростёт)
{
par1World.setBlockWithNotify(par2, par3 + 1, par4, blockID);
par1World.setBlockMetadataWithNotify(par2, par3, par4, 0);
}
else
{
par1World.setBlockMetadataWithNotify(par2, par3, par4, j + 1);
}
}
}
}
/**
* Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
*/
public boolean canPlaceBlockAt(World par1World, int x, int y, int z)//можно ли ставить блок
{
int i = par1World.getBlockId(x, y - 1, z);
if((par1World.getBlockId(x, y-1, z) == blockID)||(par1World.getBlockId(x, y-1, z) == Block.dirt.blockID)||(par1World.getBlockId(x, y-1, z) == Block.grass.blockID))
return true;
return false;//да
}
/**
* Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
* their own) Args: x, y, z, neighbor blockID
*/
public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
{
checkBlockCoordValid(par1World, par2, par3, par4);
}
/**
* Checks if current block pos is valid, if not, breaks the block as dropable item. Used for reed and cactus.
*/
protected final void checkBlockCoordValid(World par1World, int par2, int par3, int par4)
{
if (!canBlockStay(par1World, par2, par3, par4))
{
dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
par1World.setBlockWithNotify(par2, par3, par4, 0);
}
}
/**
* Can this block stay at this position. Similar to canPlaceBlockAt except gets checked often with plants.
*/
public boolean canBlockStay(World par1World, int x, int y, int z) //где можно будет посадить растение
{
if((par1World.getBlockId(x, y-1, z) == blockID)||(par1World.getBlockId(x, y-1, z) == Block.dirt.blockID)||(par1World.getBlockId(x, y-1, z) == Block.grass.blockID))
return true;
return false;
}
public void onEntityCollidedWithBlock(World par1World, int x, int y, int z, Entity par5Entity)
{
par5Entity.attackEntityFrom(DamageSource.cactus, 1);//атака игрока
}
/**
* Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
* cleared to be reused)
*/
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int i)//оптическая рамка
{
return null;
}
/**
* Returns the ID of the items to drop on destruction.
*/
public int idDropped(int par1, Random par2Random, int par3)//выбрасываем по id
{
return Item.rose.shiftedIndex;
}
public boolean isOpaqueCube()//делаем блок непрозрачным
{
return false;
}
/**
* If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
*/
public boolean renderAsNormalBlock()
{
return false;
}
/**
* The type of render function that is called for this block
*/
public int getRenderType()
{
return 1;
}
}
2. Добавляем новый блок как описано выше
Пример
roseblock = new BlockRose(162, 168).setHardness(0.5F).setResistance(0.3F).setLightValue(0F).setBlockName("rose");
3. Создаём файл с названием BlockRose (в нашем случае)
4. Добавляем в файл следующие строки
package net.minecraft.src;
import java.util.Random;
public class BlockRose extends Block
{
protected BlockRose(int par1, int par2)
{
super(par1, Material.plants);//материал растение
blockIndexInTexture = par2;
float f = 0.375F;
setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 1.0F, 0.5F + f);
setTickRandomly(true);
}
/**
* Ticks the block if it's been scheduled
*/
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)//Это сам алгоритм роста.
{
if (par1World.isAirBlock(par2, par3 + 1, par4))
{
int i;
for (i = 1; par1World.getBlockId(par2, par3 - i, par4) == blockID; i++) { }
if (i < 5) //Вырастает до 4-х блоков (если хотим, что бы рост был до 5-ти, то пишем число 6, всегда на единицу БОЛЬШЕ)
{
int j = par1World.getBlockMetadata(par2, par3, par4);
if (j == 15) //скорость роста (чем меньше значение, тем быстрее ростёт)
{
par1World.setBlockWithNotify(par2, par3 + 1, par4, blockID);
par1World.setBlockMetadataWithNotify(par2, par3, par4, 0);
}
else
{
par1World.setBlockMetadataWithNotify(par2, par3, par4, j + 1);
}
}
}
}
/**
* Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
*/
public boolean canPlaceBlockAt(World par1World, int x, int y, int z)//можно ли ставить блок
{
int i = par1World.getBlockId(x, y - 1, z);
if((par1World.getBlockId(x, y-1, z) == blockID)||(par1World.getBlockId(x, y-1, z) == Block.dirt.blockID)||(par1World.getBlockId(x, y-1, z) == Block.grass.blockID))
return true;
return false;//да
}
/**
* Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
* their own) Args: x, y, z, neighbor blockID
*/
public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
{
checkBlockCoordValid(par1World, par2, par3, par4);
}
/**
* Checks if current block pos is valid, if not, breaks the block as dropable item. Used for reed and cactus.
*/
protected final void checkBlockCoordValid(World par1World, int par2, int par3, int par4)
{
if (!canBlockStay(par1World, par2, par3, par4))
{
dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
par1World.setBlockWithNotify(par2, par3, par4, 0);
}
}
/**
* Can this block stay at this position. Similar to canPlaceBlockAt except gets checked often with plants.
*/
public boolean canBlockStay(World par1World, int x, int y, int z) //где можно будет посадить растение
{
if((par1World.getBlockId(x, y-1, z) == blockID)||(par1World.getBlockId(x, y-1, z) == Block.dirt.blockID)||(par1World.getBlockId(x, y-1, z) == Block.grass.blockID))
return true;
return false;
}
public void onEntityCollidedWithBlock(World par1World, int x, int y, int z, Entity par5Entity)
{
par5Entity.attackEntityFrom(DamageSource.cactus, 1);//атака игрока
}
/**
* Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
* cleared to be reused)
*/
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int i)//оптическая рамка
{
return null;
}
/**
* Returns the ID of the items to drop on destruction.
*/
public int idDropped(int par1, Random par2Random, int par3)//выбрасываем по id
{
return Item.rose.shiftedIndex;
}
public boolean isOpaqueCube()//делаем блок непрозрачным
{
return false;
}
/**
* If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
*/
public boolean renderAsNormalBlock()
{
return false;
}
/**
* The type of render function that is called for this block
*/
public int getRenderType()
{
return 1;
}
}
8. Создание моба (враждебный и дружелюбный) (1.3.2)
1. Создадим файл EntityMobNew.java
package net.minecraft.src;
import java.util.Random;
public class EntityMobNew extends EntityMob // если хотите мирного моба, то пишите - public class EntityMobNew extends EntityCreature
{
private static final ItemStack defaultHeldItem = new ItemStack(Item.bow, 1); //Даём в руку "лук"
public EntityMobNew(World par1World)
{
super(par1World);
this.texture = "/mob/zombie.png";//скин для моба
this.moveSpeed = 0.2F;//скорость перемещения
this.attackStrength = 4; //атака игрока //только для враждебного моба (если мирный, то удалите)
this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityAIBreakDoor(this));
this.tasks.addTask(2, new EntityAIAttackOnCollide(this, net.minecraft.src.EntityPlayer.class, moveSpeed, false)); //только для враждебного моба (если мирный, то удалите)
//this.tasks.addTask(2, new EntityAIRestrictSun(this));//горит на солнце
//this.tasks.addTask(3, new EntityAIFleeSun(this, moveSpeed));//бежит от солнца
this.tasks.addTask(3, new EntityAIWander(this, moveSpeed));
this.tasks.addTask(4, new EntityAIWatchClosest(this, net.minecraft.src.EntityPlayer.class, 8F));
this.tasks.addTask(5, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, net.minecraft.src.EntityPlayer.class, 16F, 0, true));//только для враждебного моба (если мирный, то удалите)
this.tasks.addTask(3, new EntityAIAttackOnCollide(this, net.minecraft.src.EntityZombie.class, moveSpeed, true));//атакует зомби только для враждебного моба (если мирный, то удалите)
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, net.minecraft.src.EntityZombie.class, 16F, 0, false)); //только для враждебного моба (если мирный, то удалите)
this.tasks.addTask(3, new EntityAIAttackOnCollide(this, net.minecraft.src.EntitySkeleton.class, moveSpeed, true));//атакует скелетов только для враждебного моба (если мирный, то удалите)
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, net.minecraft.src.EntitySkeleton.class, 16F, 0, false));//только для враждебного моба (если мирный, то удалите)
this.tasks.addTask(3, new EntityAIAttackOnCollide(this, net.minecraft.src.EntitySpider.class, moveSpeed, true));//атакует пауков только для враждебного моба (если мирный, то удалите)
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, net.minecraft.src.EntitySpider.class, 16F, 0, false));//только для враждебного моба (если мирный, то удалите)
}
/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}
public int getMaxHealth()
{
return 100; //ХП моба
}
/**
* Returns the sound this mob makes while it's alive.
*/
protected String getLivingSound()
{
return "mob.zombie"; //постоянное издование звуков
}
/**
* Returns the sound this mob makes when it is hurt.
*/
protected String getHurtSound()
{
return "mob.zombiehurt";//звук при получении урона
}
/**
* Returns the sound this mob makes on death.
*/
protected String getDeathSound()
{
return "mob.zombiedeath";//звук при смерти
}
/**
* Возвращаем предмет, который находится в руке у моба, если такой имеется
*/
public ItemStack getHeldItem()
{
return defaultHeldItem;
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEAD;
}
/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
public void onLivingUpdate()
{
super.onLivingUpdate();
}
/**
* Returns the item ID for the item the mob drops on death.
*/
protected int getDropItemId() //обязательный дроп той или иной вещи
{
return Item.arrow.shiftedIndex; //что будет выпадать
}
protected void dropRareDrop(int par1)//рандомный дроп вещей после смерти моба (если хотим, что бы выпадали ваши вещи, то меняйте названия итемов на ваши)
{
switch (rand.nextInt(4))
{
case 0:
dropItem(Item.swordSteel.shiftedIndex, 1);
break;
case 1:
dropItem(Item.helmetSteel.shiftedIndex, 1);
break;
case 2:
dropItem(Item.ingotIron.shiftedIndex, 1);
break;
case 3:
dropItem(Item.shovelSteel.shiftedIndex, 1);
break;
}
}
static
{
}
}
2. Идём в файлик EntityList.java (тут создаём яйцо для моба)
Ищем:
addMapping(EntityEnderCrystal.class, "EnderCrystal", 200);
Добавляем ниже:
addMapping(EntityMobNew.class, "MobNew", 101, 0xc1c1c1, 0x7FFF00);
Где 0xc1c1c1 - основной цвет яйца; 0x7FFF00 - цвет внешней части яйца. Везде 0x - обязательно оставляйте. Всё что после - обычная цветовая гамма HTML
3. Теперь идём в файл генерации мира BiomeGenForest.java (указываем где будет спавниться моб. В нашем случае в лесу)
Ищем:
this.spawnableCreatureList.add(new SpawnListEntry(EntityWolf.class, 5, 4, 4));
Ниже добавляем:
this.spawnableCreatureList.add(new SpawnListEntry(EntityMobNew.class, 2, 1, 1));
Если моб у нас враждебный, то меняем CreatureList на MonsterList (моб будет спавниться ночью)
Если вы хотите, что бы моб спавнился везде, то идём в BiomeGenBase.java
Ищем:
this.spawnableMonsterList.add(new SpawnListEntry(EntityEnderman.class, 1, 1, 4));
Ниже добавляем:
this.spawnableCreatureList.add(new SpawnListEntry(EntityMobNew.class, 4, 2, 5));
опять же, если моб у нас враждебный, то меняем CreatureList на MonsterList (моб будет спавниться ночью)
!!! Не забываем добавить сам скин моба в папку mob !!!
Если у вас сделан моб, не похожий на человека или любого другого прямоходящего (или же Вы хотите, что бы Ваш моб держал в руке предмет), то вам придётся создать файл ModelMobNew.java (по аналогии к примеру даже с тем же Ocelot)
import java.util.Random;
public class EntityMobNew extends EntityMob // если хотите мирного моба, то пишите - public class EntityMobNew extends EntityCreature
{
private static final ItemStack defaultHeldItem = new ItemStack(Item.bow, 1); //Даём в руку "лук"
public EntityMobNew(World par1World)
{
super(par1World);
this.texture = "/mob/zombie.png";//скин для моба
this.moveSpeed = 0.2F;//скорость перемещения
this.attackStrength = 4; //атака игрока //только для враждебного моба (если мирный, то удалите)
this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityAIBreakDoor(this));
this.tasks.addTask(2, new EntityAIAttackOnCollide(this, net.minecraft.src.EntityPlayer.class, moveSpeed, false)); //только для враждебного моба (если мирный, то удалите)
//this.tasks.addTask(2, new EntityAIRestrictSun(this));//горит на солнце
//this.tasks.addTask(3, new EntityAIFleeSun(this, moveSpeed));//бежит от солнца
this.tasks.addTask(3, new EntityAIWander(this, moveSpeed));
this.tasks.addTask(4, new EntityAIWatchClosest(this, net.minecraft.src.EntityPlayer.class, 8F));
this.tasks.addTask(5, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, net.minecraft.src.EntityPlayer.class, 16F, 0, true));//только для враждебного моба (если мирный, то удалите)
this.tasks.addTask(3, new EntityAIAttackOnCollide(this, net.minecraft.src.EntityZombie.class, moveSpeed, true));//атакует зомби только для враждебного моба (если мирный, то удалите)
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, net.minecraft.src.EntityZombie.class, 16F, 0, false)); //только для враждебного моба (если мирный, то удалите)
this.tasks.addTask(3, new EntityAIAttackOnCollide(this, net.minecraft.src.EntitySkeleton.class, moveSpeed, true));//атакует скелетов только для враждебного моба (если мирный, то удалите)
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, net.minecraft.src.EntitySkeleton.class, 16F, 0, false));//только для враждебного моба (если мирный, то удалите)
this.tasks.addTask(3, new EntityAIAttackOnCollide(this, net.minecraft.src.EntitySpider.class, moveSpeed, true));//атакует пауков только для враждебного моба (если мирный, то удалите)
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, net.minecraft.src.EntitySpider.class, 16F, 0, false));//только для враждебного моба (если мирный, то удалите)
}
/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}
public int getMaxHealth()
{
return 100; //ХП моба
}
/**
* Returns the sound this mob makes while it's alive.
*/
protected String getLivingSound()
{
return "mob.zombie"; //постоянное издование звуков
}
/**
* Returns the sound this mob makes when it is hurt.
*/
protected String getHurtSound()
{
return "mob.zombiehurt";//звук при получении урона
}
/**
* Returns the sound this mob makes on death.
*/
protected String getDeathSound()
{
return "mob.zombiedeath";//звук при смерти
}
/**
* Возвращаем предмет, который находится в руке у моба, если такой имеется
*/
public ItemStack getHeldItem()
{
return defaultHeldItem;
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEAD;
}
/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
public void onLivingUpdate()
{
super.onLivingUpdate();
}
/**
* Returns the item ID for the item the mob drops on death.
*/
protected int getDropItemId() //обязательный дроп той или иной вещи
{
return Item.arrow.shiftedIndex; //что будет выпадать
}
protected void dropRareDrop(int par1)//рандомный дроп вещей после смерти моба (если хотим, что бы выпадали ваши вещи, то меняйте названия итемов на ваши)
{
switch (rand.nextInt(4))
{
case 0:
dropItem(Item.swordSteel.shiftedIndex, 1);
break;
case 1:
dropItem(Item.helmetSteel.shiftedIndex, 1);
break;
case 2:
dropItem(Item.ingotIron.shiftedIndex, 1);
break;
case 3:
dropItem(Item.shovelSteel.shiftedIndex, 1);
break;
}
}
static
{
}
}
2. Идём в файлик EntityList.java (тут создаём яйцо для моба)
Ищем:
addMapping(EntityEnderCrystal.class, "EnderCrystal", 200);
Добавляем ниже:
addMapping(EntityMobNew.class, "MobNew", 101, 0xc1c1c1, 0x7FFF00);
Где 0xc1c1c1 - основной цвет яйца; 0x7FFF00 - цвет внешней части яйца. Везде 0x - обязательно оставляйте. Всё что после - обычная цветовая гамма HTML
3. Теперь идём в файл генерации мира BiomeGenForest.java (указываем где будет спавниться моб. В нашем случае в лесу)
Ищем:
this.spawnableCreatureList.add(new SpawnListEntry(EntityWolf.class, 5, 4, 4));
Ниже добавляем:
this.spawnableCreatureList.add(new SpawnListEntry(EntityMobNew.class, 2, 1, 1));
Если моб у нас враждебный, то меняем CreatureList на MonsterList (моб будет спавниться ночью)
Если вы хотите, что бы моб спавнился везде, то идём в BiomeGenBase.java
Ищем:
this.spawnableMonsterList.add(new SpawnListEntry(EntityEnderman.class, 1, 1, 4));
Ниже добавляем:
this.spawnableCreatureList.add(new SpawnListEntry(EntityMobNew.class, 4, 2, 5));
опять же, если моб у нас враждебный, то меняем CreatureList на MonsterList (моб будет спавниться ночью)
!!! Не забываем добавить сам скин моба в папку mob !!!
Если у вас сделан моб, не похожий на человека или любого другого прямоходящего (или же Вы хотите, что бы Ваш моб держал в руке предмет), то вам придётся создать файл ModelMobNew.java (по аналогии к примеру даже с тем же Ocelot)
1. Создадим файл ModelMobNew.java:
package net.minecraft.src;
public class ModelMobNew extends ModelBiped
{
public ModelMobNew()
{
}
/**
* Sets the models various rotation angles.
*/
public void setRotationAngles(float par1, float par2)//изменяем внутри, если хотим что бы моб был не прямоходящим (и убираем теги закоментированного кода - /* ... */)
{
/*super.setRotationAngles(par1, par2, par3, par4, par5, par6);
float f = MathHelper.sin(onGround * (float)Math.PI);
float f1 = MathHelper.sin((1.0F - (1.0F - onGround) * (1.0F - onGround)) * (float)Math.PI);
bipedRightArm.rotateAngleZ = 0.0F;
bipedLeftArm.rotateAngleZ = 0.0F;
bipedRightArm.rotateAngleY = -(0.1F - f * 0.6F);
bipedLeftArm.rotateAngleY = 0.1F - f * 0.6F;
bipedRightArm.rotateAngleX = -((float)Math.PI / 2F);
bipedLeftArm.rotateAngleX = -((float)Math.PI / 2F);
bipedRightArm.rotateAngleX -= f * 1.2F - f1 * 0.4F;
bipedLeftArm.rotateAngleX -= f * 1.2F - f1 * 0.4F;
bipedRightArm.rotateAngleZ += MathHelper.cos(par3 * 0.09F) * 0.05F + 0.05F;
bipedLeftArm.rotateAngleZ -= MathHelper.cos(par3 * 0.09F) * 0.05F + 0.05F;
bipedRightArm.rotateAngleX += MathHelper.sin(par3 * 0.067F) * 0.05F;
bipedLeftArm.rotateAngleX -= MathHelper.sin(par3 * 0.067F) * 0.05F;*/
}
}
2. Идем в файл RenderManager.java
Ищем:
private RenderManager()
{
Дописываем ниже:
this.entityRenderMap.put(net.minecraft.src.EntityMobNew.class, new RenderBiped(new ModelMobNew(), 0.5F));
package net.minecraft.src;
public class ModelMobNew extends ModelBiped
{
public ModelMobNew()
{
}
/**
* Sets the models various rotation angles.
*/
public void setRotationAngles(float par1, float par2)//изменяем внутри, если хотим что бы моб был не прямоходящим (и убираем теги закоментированного кода - /* ... */)
{
/*super.setRotationAngles(par1, par2, par3, par4, par5, par6);
float f = MathHelper.sin(onGround * (float)Math.PI);
float f1 = MathHelper.sin((1.0F - (1.0F - onGround) * (1.0F - onGround)) * (float)Math.PI);
bipedRightArm.rotateAngleZ = 0.0F;
bipedLeftArm.rotateAngleZ = 0.0F;
bipedRightArm.rotateAngleY = -(0.1F - f * 0.6F);
bipedLeftArm.rotateAngleY = 0.1F - f * 0.6F;
bipedRightArm.rotateAngleX = -((float)Math.PI / 2F);
bipedLeftArm.rotateAngleX = -((float)Math.PI / 2F);
bipedRightArm.rotateAngleX -= f * 1.2F - f1 * 0.4F;
bipedLeftArm.rotateAngleX -= f * 1.2F - f1 * 0.4F;
bipedRightArm.rotateAngleZ += MathHelper.cos(par3 * 0.09F) * 0.05F + 0.05F;
bipedLeftArm.rotateAngleZ -= MathHelper.cos(par3 * 0.09F) * 0.05F + 0.05F;
bipedRightArm.rotateAngleX += MathHelper.sin(par3 * 0.067F) * 0.05F;
bipedLeftArm.rotateAngleX -= MathHelper.sin(par3 * 0.067F) * 0.05F;*/
}
}
2. Идем в файл RenderManager.java
Ищем:
private RenderManager()
{
Дописываем ниже:
this.entityRenderMap.put(net.minecraft.src.EntityMobNew.class, new RenderBiped(new ModelMobNew(), 0.5F));

9. Создание своего биома (1.3.2)
1. Вам нужно создать новый файл под именем BiomeGenNewBiome.java
Пример файла:
package net.minecraft.src;
import java.util.List;
public class BiomeGenNewBiome extends BiomeGenBase
{
public BiomeGenNewBiome(int par1)
{
super(par1);
this.spawnableCreatureList.clear();//либо запрещаем спавнится мобам, либо удаляем и вставляем то, что ниже
this.spawnableCreatureList.add(new SpawnListEntry(net.minecraft.src.EntityWolf.class, 5, 4, 4));//Разрешаем спавнится волку в этом биоме (или удалите, тогда оставьте то, что выше)
this.topBlock = (byte)Block.gold.blockID; //это верхний слой блоков, первое что вы увидите, будет этот блок
this.fillerBlock = (byte)Block.dirt.blockID;//слой толщиной 3-5 блоков под topBlock
this.theBiomeDecorator.treesPerChunk = 10; //количество деревьев на 1 чанк
this.theBiomeDecorator.grassPerChunk = 2; //количество травы на 1 чанк
}
}
2. Теперь нужно добавить ваш новый биом в BiomeGenBase.java
Ищем строчку
public static final BiomeGenBase jungleHills = (new BiomeGenJungle(22)).setColor(2900485).setBiomeName("JungleHills").func_76733_a(5470985).setTemperatureRainfall(1.2F, 0.9F).setMinMaxHeight(1.8F, 0.5F);
Добавляем после неё
public static final BiomeGenBase newBiome = (new BiomeGenNewBiome(23)).setColor(0xfade55).setBiomeName("NewBiome").setTemperatureRainfall(0.8F, 0.4F).setMinMaxHeight(0.0F, 0.1F);
Где:
newBiome - само название биома
23 - ID биома (Пишите свободные номера, по стандарту свободные начинаются с 23)
setColor - цвет биома (0x обязательно должно быть, всё остальное - код цвета HTML)
setTemperatureRainfall - температура на биоме
setMinMaxHeight - минимальная и максимальная высота биома
3. Теперь идём в файл GenLayerBiome (в нём прописываем, что бы ваш биом появился в мире)
Ищем:
BiomeGenBase.taiga,
После, вставляем:
BiomeGenBase.newBiome
Там две строчки похожие, вставляем и там и там
Пример файла:
package net.minecraft.src;
import java.util.List;
public class BiomeGenNewBiome extends BiomeGenBase
{
public BiomeGenNewBiome(int par1)
{
super(par1);
this.spawnableCreatureList.clear();//либо запрещаем спавнится мобам, либо удаляем и вставляем то, что ниже
this.spawnableCreatureList.add(new SpawnListEntry(net.minecraft.src.EntityWolf.class, 5, 4, 4));//Разрешаем спавнится волку в этом биоме (или удалите, тогда оставьте то, что выше)
this.topBlock = (byte)Block.gold.blockID; //это верхний слой блоков, первое что вы увидите, будет этот блок
this.fillerBlock = (byte)Block.dirt.blockID;//слой толщиной 3-5 блоков под topBlock
this.theBiomeDecorator.treesPerChunk = 10; //количество деревьев на 1 чанк
this.theBiomeDecorator.grassPerChunk = 2; //количество травы на 1 чанк
}
}
2. Теперь нужно добавить ваш новый биом в BiomeGenBase.java
Ищем строчку
public static final BiomeGenBase jungleHills = (new BiomeGenJungle(22)).setColor(2900485).setBiomeName("JungleHills").func_76733_a(5470985).setTemperatureRainfall(1.2F, 0.9F).setMinMaxHeight(1.8F, 0.5F);
Добавляем после неё
public static final BiomeGenBase newBiome = (new BiomeGenNewBiome(23)).setColor(0xfade55).setBiomeName("NewBiome").setTemperatureRainfall(0.8F, 0.4F).setMinMaxHeight(0.0F, 0.1F);
Где:
newBiome - само название биома
23 - ID биома (Пишите свободные номера, по стандарту свободные начинаются с 23)
setColor - цвет биома (0x обязательно должно быть, всё остальное - код цвета HTML)
setTemperatureRainfall - температура на биоме
setMinMaxHeight - минимальная и максимальная высота биома
3. Теперь идём в файл GenLayerBiome (в нём прописываем, что бы ваш биом появился в мире)
Ищем:
BiomeGenBase.taiga,
После, вставляем:
BiomeGenBase.newBiome
Там две строчки похожие, вставляем и там и там
10. Создание инструментов
1) Зарегистрируем кирку в Item.java
2) Добавим новый материал и дадим ему характеристики.
3) Теперь добавим рецепт нашей кирки.
4) Добавление имени.
Как сделать меч, топор, лопату.
public static ItemMap map = (ItemMap)(new ItemMap(102)).setIconCoord(12, 3).setItemName("map");
Ищем
добавляем строчку
public static Item pickaxeDirt;
Листаем в самый низ и добавляем
pickaxeDirt = (new ItemPickaxe(130, EnumToolMaterial.DIRT)).setIconCoord(3, 6).setItemName("pickaxeDirt");
130 - id кирки
DIRT - новый материал
3 и 6 это координаты
Дальше идёт название кирки
Ищем
добавляем строчку
public static Item pickaxeDirt;
Листаем в самый низ и добавляем
pickaxeDirt = (new ItemPickaxe(130, EnumToolMaterial.DIRT)).setIconCoord(3, 6).setItemName("pickaxeDirt");
130 - id кирки
DIRT - новый материал
3 и 6 это координаты
Дальше идёт название кирки
2) Добавим новый материал и дадим ему характеристики.
Открываем EnumToolMaterial и находим
GOLD(0, 32, 12F, 0, 22);
";" меняем на "," и дописываем
DIRT(0, 59, 2.0F, 0, 15);
GOLD(0, 32, 12F, 0, 22);
";" меняем на "," и дописываем
DIRT(0, 59, 2.0F, 0, 15);
3) Теперь добавим рецепт нашей кирки.
Идём в CraftingManager
ищем
addShapelessRecipe(new ItemStack(Item.fireballCharge, 3), new Object[]
{
Item.gunpowder, Item.blazePowder, new ItemStack(Item.coal, 1, 1)
});
и после этого ставим
addRecipe(new ItemStack(Item.pickaxeDirt, 1), new Object []
{
"DDD", " S ", " S ", 'D', Block.dirt, 'S', Item.stick
});
Крафтится также как и любая кирка, только вместо железа, золота и т.д., угадайте что.
ищем
addShapelessRecipe(new ItemStack(Item.fireballCharge, 3), new Object[]
{
Item.gunpowder, Item.blazePowder, new ItemStack(Item.coal, 1, 1)
});
и после этого ставим
addRecipe(new ItemStack(Item.pickaxeDirt, 1), new Object []
{
"DDD", " S ", " S ", 'D', Block.dirt, 'S', Item.stick
});
Крафтится также как и любая кирка, только вместо железа, золота и т.д., угадайте что.
4) Добавление имени.
Идём в minecraft.jar/lang, открываем ru_RU.lang и после
item.fireball.name=Огненный шар
пишем
item.pickaxeDirtl.name=Земленая кирка
(название не придумал)
item.fireball.name=Огненный шар
пишем
item.pickaxeDirtl.name=Земленая кирка
(название не придумал)
Как сделать меч, топор, лопату.
Делается точно также, только вместо pickaxe пишем: axe - топор, sword - меч, shovel - лопата.
Example
public static Item axeDirt;
axeDirt = (new ItemAxe(130, EnumToolMaterial.DIRT)).setIconCoord(3, 6).setItemName("axeDirt");
addRecipe(new ItemStack(Item.axeDirt, 1), new Object []
{
"DD ", "DS ", " S ", 'D', Block.dirt, 'S', Item.stick
});
item.axeDirtl.name=Земленой топор
Это топор.
Example
public static Item axeDirt;
axeDirt = (new ItemAxe(130, EnumToolMaterial.DIRT)).setIconCoord(3, 6).setItemName("axeDirt");
addRecipe(new ItemStack(Item.axeDirt, 1), new Object []
{
"DD ", "DS ", " S ", 'D', Block.dirt, 'S', Item.stick
});
item.axeDirtl.name=Земленой топор
Это топор.
11. Создание брони на основе новых материалов
1) Для начала откроем файл Item.java.
2) Добавление своих характеристик.
3) Затем добавим рецепт.
4) Сейчас мы добавим имя нашей броне.
Инглиш версия en_US.lang
Найдём строчку
public static ItemMap map = (ItemMap)(new ItemMap(102)).setIconCoord(12, 3).setItemName("map");
и после неё пишем
public static Item helmetWood;
public static Item plateWood;
public static Item legsWood;
public static Item bootsWood;
Затем листаем в самый низ и после
speckledMelon = (new Item(126)).setIconCoord(9, 8).setItemName("speckledMelon").setPotionEffect(PotionHelper.speckledMelonEffect);
пишем
helmetWood = (new ItemArmor(130, EnumArmorMaterial.WOOD, 5, 0)).setIconCoord(0, 9).setItemName("helmetWood");
plateWood = (new ItemArmor(131, EnumArmorMaterial.WOOD, 5, 1)).setIconCoord(0, 10).setItemName("chestplateWood");
legsWood = (new ItemArmor(132, EnumArmorMaterial.WOOD, 5, 2)).setIconCoord(0, 11).setItemName("leggingsWood");
bootsWood = (new ItemArmor(133, EnumArmorMaterial.WOOD, 5, 3)).setIconCoord(0, 12).setItemName("bootsWood");
130 - id(рекомендую использовать с 130).
WOOD - материал.
5 - порядковый номер (0 - кожа, 1 - кольчуга, 2 - железо, 3 - алмаз, 4 - золото).
0 - шлем, 1 - нагрудник, 2 - штаны, 3 - носки).
0 и 9 это координаты.
setItemName - название брони.
public static ItemMap map = (ItemMap)(new ItemMap(102)).setIconCoord(12, 3).setItemName("map");
и после неё пишем
public static Item helmetWood;
public static Item plateWood;
public static Item legsWood;
public static Item bootsWood;
Затем листаем в самый низ и после
speckledMelon = (new Item(126)).setIconCoord(9, 8).setItemName("speckledMelon").setPotionEffect(PotionHelper.speckledMelonEffect);
пишем
helmetWood = (new ItemArmor(130, EnumArmorMaterial.WOOD, 5, 0)).setIconCoord(0, 9).setItemName("helmetWood");
plateWood = (new ItemArmor(131, EnumArmorMaterial.WOOD, 5, 1)).setIconCoord(0, 10).setItemName("chestplateWood");
legsWood = (new ItemArmor(132, EnumArmorMaterial.WOOD, 5, 2)).setIconCoord(0, 11).setItemName("leggingsWood");
bootsWood = (new ItemArmor(133, EnumArmorMaterial.WOOD, 5, 3)).setIconCoord(0, 12).setItemName("bootsWood");
130 - id(рекомендую использовать с 130).
WOOD - материал.
5 - порядковый номер (0 - кожа, 1 - кольчуга, 2 - железо, 3 - алмаз, 4 - золото).
0 - шлем, 1 - нагрудник, 2 - штаны, 3 - носки).
0 и 9 это координаты.
setItemName - название брони.
Откроем EnumArmorMaterial.ja.va
Ищем строчку
DIAMOND(33, new int[] {
3, 8, 6, 3
}, 10);
Убираем ";" и ставим знак ",". Затем, после этого вставляем
WOOD(6, new int[] {
2, 5, 1, 2
}, 17);
У дерева приблизительно те же свойства, что и у кожи.
Ищем строчку
DIAMOND(33, new int[] {
3, 8, 6, 3
}, 10);
Убираем ";" и ставим знак ",". Затем, после этого вставляем
WOOD(6, new int[] {
2, 5, 1, 2
}, 17);
У дерева приблизительно те же свойства, что и у кожи.
3) Затем добавим рецепт.
Открываем RecipesArmor.java и после
Item.ingotGold
ставим запятую и пишем
Block.planks
ниже
}, new Object[] {
Item.helmetLeather, Item.helmetChain, Item.helmetSteel, Item.helmetDiamond, Item.helmetGold
}, new Object[] {
Item.plateLeather, Item.plateChain, Item.plateSteel, Item.plateDiamond, Item.plateGold
}, new Object[] {
Item.legsLeather, Item.legsChain, Item.legsSteel, Item.legsDiamond, Item.legsGold
}, new Object[] {
Item.bootsLeather, Item.bootsChain, Item.bootsSteel, Item.bootsDiamond, Item.bootsGold
}
заменяем на
}, new Object[] {
Item.helmetLeather, Item.helmetChain, Item.helmetSteel, Item.helmetDiamond, Item.helmetGold, Item.helmetWood
}, new Object[] {
Item.plateLeather, Item.plateChain, Item.plateSteel, Item.plateDiamond, Item.plateGold, Item.plateWood
}, new Object[] {
Item.legsLeather, Item.legsChain, Item.legsSteel, Item.legsDiamond, Item.legsGold, Item.legsWood
}, new Object[] {
Item.bootsLeather, Item.bootsChain, Item.bootsSteel, Item.bootsDiamond, Item.bootsGold, Item.bootsWood
}
Item.ingotGold
ставим запятую и пишем
Block.planks
ниже
}, new Object[] {
Item.helmetLeather, Item.helmetChain, Item.helmetSteel, Item.helmetDiamond, Item.helmetGold
}, new Object[] {
Item.plateLeather, Item.plateChain, Item.plateSteel, Item.plateDiamond, Item.plateGold
}, new Object[] {
Item.legsLeather, Item.legsChain, Item.legsSteel, Item.legsDiamond, Item.legsGold
}, new Object[] {
Item.bootsLeather, Item.bootsChain, Item.bootsSteel, Item.bootsDiamond, Item.bootsGold
}
заменяем на
}, new Object[] {
Item.helmetLeather, Item.helmetChain, Item.helmetSteel, Item.helmetDiamond, Item.helmetGold, Item.helmetWood
}, new Object[] {
Item.plateLeather, Item.plateChain, Item.plateSteel, Item.plateDiamond, Item.plateGold, Item.plateWood
}, new Object[] {
Item.legsLeather, Item.legsChain, Item.legsSteel, Item.legsDiamond, Item.legsGold, Item.legsWood
}, new Object[] {
Item.bootsLeather, Item.bootsChain, Item.bootsSteel, Item.bootsDiamond, Item.bootsGold, Item.bootsWood
}
4) Сейчас мы добавим имя нашей броне.
Заходим в minecraft.jar/lang/, открываем ru_RU.lang
Ищем строчку item.fireball.name=Огненный шар и ниже пишем
item.helmetWood.name=Деревянный шлем
item.chestplateWood.name=Деревянная куртка
item.leggingsWood.name=Деревянные штаны
item.bootsWood.name=Деревянные ботинки
Вот и всё)
Ищем строчку item.fireball.name=Огненный шар и ниже пишем
item.helmetWood.name=Деревянный шлем
item.chestplateWood.name=Деревянная куртка
item.leggingsWood.name=Деревянные штаны
item.bootsWood.name=Деревянные ботинки
Вот и всё)
Инглиш версия en_US.lang
item.helmetWood.name=Wooden Helmet
item.chestplateWood.name=Wooden Plate
item.leggingsWood.name=Wooden Leggins
item.bootsWood.name=Wooden Boots
item.chestplateWood.name=Wooden Plate
item.leggingsWood.name=Wooden Leggins
item.bootsWood.name=Wooden Boots
12. Создание еды (с эффектами) (1.3.2)
1) Для начала откроем файл Item.java.
2) Найдём данные строки:
/** Item index + 256 */
public final int shiftedIndex;
И над этим кодом добавим еду (итем)
public static Item newFood = (new ItemFood(133, 4, 0.3F, false)).setIconCoord(10, 0).setItemName("newFood").setAlwaysEdible();
Item newFood - название предмета (еды)
(new ItemFood( - говорит, что данный итем - еда (и посылается в файл ItemFood.java)
133 - ID предмета
4 - восполнение "полосок" голода
0.3F - *пока не разбирался*
false - приручение волка (да/нет)
setIconCoord(10, 0) - координаты текстуры в файле items.png
setItemName("newFood") - переменная (имя) для перевода через lang файл
.setAlwaysEdible() - всегда можно кушать
Если вы хотите добавить эффект к еде, то смотрите (остальные эффекты в файле Potion.java):
После:
(new ItemFood(133, 4, 0.3F, false)).setAlwaysEdible().
Вставляем:
1) Регенерация здоровья (Этот участок кода говорит, что если вы скушаете данную еду, то она будет регенерировать ваше здоровье определённое кол-во времени)
setPotionEffect(Potion.regeneration.id, 5, 0, 1.0F).
2) Отравление (Этот участок кода говорит, что если вы скушаете данную еду, то вы будете голодать определённое кол-во времени)
setPotionEffect(Potion.hunger.id, 30, 0, 0.8F).
Этот участок кода говорит, что если вы скушаете данную еду, то она будет регенерировать ваше здоровье определённое кол-во времени
5(30) - длительность эффекта
0 - интенсивность
1.0F(0.8F) - вероятность эффекта
2) Найдём данные строки:
/** Item index + 256 */
public final int shiftedIndex;
И над этим кодом добавим еду (итем)
public static Item newFood = (new ItemFood(133, 4, 0.3F, false)).setIconCoord(10, 0).setItemName("newFood").setAlwaysEdible();
Item newFood - название предмета (еды)
(new ItemFood( - говорит, что данный итем - еда (и посылается в файл ItemFood.java)
133 - ID предмета
4 - восполнение "полосок" голода
0.3F - *пока не разбирался*
false - приручение волка (да/нет)
setIconCoord(10, 0) - координаты текстуры в файле items.png
setItemName("newFood") - переменная (имя) для перевода через lang файл
.setAlwaysEdible() - всегда можно кушать
Если вы хотите добавить эффект к еде, то смотрите (остальные эффекты в файле Potion.java):
После:
(new ItemFood(133, 4, 0.3F, false)).setAlwaysEdible().
Вставляем:
1) Регенерация здоровья (Этот участок кода говорит, что если вы скушаете данную еду, то она будет регенерировать ваше здоровье определённое кол-во времени)
setPotionEffect(Potion.regeneration.id, 5, 0, 1.0F).
2) Отравление (Этот участок кода говорит, что если вы скушаете данную еду, то вы будете голодать определённое кол-во времени)
setPotionEffect(Potion.hunger.id, 30, 0, 0.8F).
Этот участок кода говорит, что если вы скушаете данную еду, то она будет регенерировать ваше здоровье определённое кол-во времени
5(30) - длительность эффекта
0 - интенсивность
1.0F(0.8F) - вероятность эффекта
13. Создание достижений
1. Откроем файл AchievementList.java
2. Найдём строки:
/** Is the 'Librarian' achievement */
public static Achievement bookcase = (new Achievement(26, "bookcase", -3, 6, Block.bookShelf, enchantments)).registerAchievement();
3. После, добавим:
public static Achievement mineDirt = (new Achievement(27, "mineDirt", 0, 0, Block.dirt, (Achievement)null)).registerAchievement();
Achievement mineDirt - название достижения
27 - ID достижения (свободные начинаются с 27)
"mineDirt" - перевод через lang файл
Block.dirt - при добыче КАКОГО блока (предмета) засчитывать достижение
(Achievement)null)) - независимое достижение, то есть ни как с досками, что бы сначала получить дерево, потом скрафтить из него доски.
registerAchievement() - регистрируем достижение
4. Откроем файл EntityItem.java и найдём в нём:
if (this.item.itemID == Block.wood.blockID)
{
par1EntityPlayer.triggerAchievement(AchievementList.mineWood);
}
5. Добавим после:
if (this.item.itemID == Block.dirt.blockID)
{
par1EntityPlayer.triggerAchievement(AchievementList.mineDirt);
}
То есть при добыче земли (в нашем случае) выводить надпись о выполнении достижения с картинкой данного блока (предмета)
2. Найдём строки:
/** Is the 'Librarian' achievement */
public static Achievement bookcase = (new Achievement(26, "bookcase", -3, 6, Block.bookShelf, enchantments)).registerAchievement();
3. После, добавим:
public static Achievement mineDirt = (new Achievement(27, "mineDirt", 0, 0, Block.dirt, (Achievement)null)).registerAchievement();
Achievement mineDirt - название достижения
27 - ID достижения (свободные начинаются с 27)
"mineDirt" - перевод через lang файл
Block.dirt - при добыче КАКОГО блока (предмета) засчитывать достижение
(Achievement)null)) - независимое достижение, то есть ни как с досками, что бы сначала получить дерево, потом скрафтить из него доски.
registerAchievement() - регистрируем достижение
4. Откроем файл EntityItem.java и найдём в нём:
if (this.item.itemID == Block.wood.blockID)
{
par1EntityPlayer.triggerAchievement(AchievementList.mineWood);
}
5. Добавим после:
if (this.item.itemID == Block.dirt.blockID)
{
par1EntityPlayer.triggerAchievement(AchievementList.mineDirt);
}
То есть при добыче земли (в нашем случае) выводить надпись о выполнении достижения с картинкой данного блока (предмета)
14. Создание рецепта для печки (1.3.2)
1. Открываем файл FurnaceRecipes.java
2. Ищем строчку
this.addSmelting(Block.oreLapis.blockID, new ItemStack(Item.dyePowder, 1, 4), 0.2F);
3. После, добавляем
this.addSmelting(Item.baseItem.shiftedIndex, new ItemStack(Item.resultItem));
Где:
Item.baseItem - предмет, который кладём в печку
Item.resultItem - предмет, который в итоге получится после плавки
Если вы хотите плавить блок, то добавляем что-то на подобии этого:
this.addSmelting(Block.baseBlock.blockID, new ItemStack(Item.resultItem), 0.2F);
Где:
Block.baseBlock - блок, который кладём в печку
Item.resultItem - предмет, который получается в итоге
Если вы хотите после плавки получить не предмет, а блок, то вместо:
new ItemStack(Item.resultItem), 0.2F);
Пишите:
new ItemStack(Block.glass), 0.1F);
2. Ищем строчку
this.addSmelting(Block.oreLapis.blockID, new ItemStack(Item.dyePowder, 1, 4), 0.2F);
3. После, добавляем
this.addSmelting(Item.baseItem.shiftedIndex, new ItemStack(Item.resultItem));
Где:
Item.baseItem - предмет, который кладём в печку
Item.resultItem - предмет, который в итоге получится после плавки
Если вы хотите плавить блок, то добавляем что-то на подобии этого:
this.addSmelting(Block.baseBlock.blockID, new ItemStack(Item.resultItem), 0.2F);
Где:
Block.baseBlock - блок, который кладём в печку
Item.resultItem - предмет, который получается в итоге
Если вы хотите после плавки получить не предмет, а блок, то вместо:
new ItemStack(Item.resultItem), 0.2F);
Пишите:
new ItemStack(Block.glass), 0.1F);
15. Делаем предмет топливом для печки (1.3.2)
1. Открываем файл TileEntityFurnace.java
2. Ищем строчку
return var2 instanceof ItemTool && ((ItemTool)var2).func_77861_e().equals("WOOD") ? 200 : (var2 instanceof ItemSword && ((ItemSword)var2).func_77825_f().equals("WOOD") ? 200 : (var2 instanceof ItemHoe && ((ItemHoe)var2).func_77842_f().equals("WOOD") ? 200 : (var1 == Item.stick.shiftedIndex ? 100 : (var1 == Item.coal.shiftedIndex ? 1600 : (var1 == Item.bucketLava.shiftedIndex ? 20000 : (var1 == Block.sapling.blockID ? 100 : (var1 == Item.blazeRod.shiftedIndex ? 2400 : 0)))))));
3. В этом коде, после этого (и до "0")
(var1 == Item.blazeRod.shiftedIndex ? 2400 :
4. Вставляем код (пример)
(var1 == Item.newItem.shiftedIndex ? 2400 :
Где:
Item.newItem - предмет, который хотим сделать топливом
2400 - время горения (к примеру время горения у "угля" - 1600, что равно 80 секунд )
2. Ищем строчку
return var2 instanceof ItemTool && ((ItemTool)var2).func_77861_e().equals("WOOD") ? 200 : (var2 instanceof ItemSword && ((ItemSword)var2).func_77825_f().equals("WOOD") ? 200 : (var2 instanceof ItemHoe && ((ItemHoe)var2).func_77842_f().equals("WOOD") ? 200 : (var1 == Item.stick.shiftedIndex ? 100 : (var1 == Item.coal.shiftedIndex ? 1600 : (var1 == Item.bucketLava.shiftedIndex ? 20000 : (var1 == Block.sapling.blockID ? 100 : (var1 == Item.blazeRod.shiftedIndex ? 2400 : 0)))))));
3. В этом коде, после этого (и до "0")
(var1 == Item.blazeRod.shiftedIndex ? 2400 :
4. Вставляем код (пример)
(var1 == Item.newItem.shiftedIndex ? 2400 :
Где:
Item.newItem - предмет, который хотим сделать топливом
2400 - время горения (к примеру время горения у "угля" - 1600, что равно 80 секунд )
16. Добавляем новый (свой) игровой режим (1.3.2)
1. Открываем файл EnumGameType.java
1.1 Ищем строку:
ADVENTURE(2, "adventure"),
1.2 Добавляем, после:
NEWMODE(3, "newmode");
newmode - имя нашего режима игры
1.3 Ищем строки:
public void configurePlayerCapabilities(PlayerCapabilities par1PlayerCapabilities)
{
if (this == CREATIVE)
{
par1PlayerCapabilities.allowFlying = true;
par1PlayerCapabilities.isCreativeMode = true;
par1PlayerCapabilities.disableDamage = true;
}
else
{
par1PlayerCapabilities.allowFlying = false;
par1PlayerCapabilities.isCreativeMode = false;
par1PlayerCapabilities.disableDamage = false;
par1PlayerCapabilities.isFlying = false;
}
par1PlayerCapabilities.allowEdit = !this.isAdventure();
}
1.4 Заменяем на:
public void configurePlayerCapabilities(PlayerCapabilities par1PlayerCapabilities)
{
if (this == CREATIVE)
{
par1PlayerCapabilities.allowFlying = true;
par1PlayerCapabilities.isCreativeMode = true;
par1PlayerCapabilities.disableDamage = true;
}
else if(this == SURVIVAL)
{
par1PlayerCapabilities.allowFlying = false;
par1PlayerCapabilities.isCreativeMode = false;
par1PlayerCapabilities.disableDamage = false;
par1PlayerCapabilities.isFlying = false;
}
else if(this == NEWMODE)
{
par1PlayerCapabilities.allowFlying = false; //разрешаем/запрещаем игроку летать по двойному прыжку
par1PlayerCapabilities.isCreativeMode = false; //если у нас режим, похожий на креатив, то пишем true, если же нет - false
par1PlayerCapabilities.disableDamage = true; //вклчюаем/отключаем получение урона
par1PlayerCapabilities.isFlying = false;
}
par1PlayerCapabilities.allowEdit = !this.isAdventure();
}
NEWMODE - имя режима, которое мы вписывали тут
2. Делаем подобие инвентаря как в "креативе"
2.1 Для того, что бы сделать инвентарь как в креативе, надо найти строки:
public boolean isCreative()
{
return this == CREATIVE;
}
2.2 И приписать наш новый режим вот таким образом:
public boolean isCreative()
{
return this == CREATIVE || this == NEWMODE;
}
NEWMODE - имя режима, которое мы вписывали тут
3. Делаем подобие инвентаря как в "выживании"
3.1 Для того, что бы сделать инвентарь как в выживании, надо найти строки:
public boolean func_77144_e()
{
return this == SURVIVAL || this == ADVENTURE;
}
3.2 И приписать наш новый режим вот таким образом:
public boolean func_77144_e()
{
return this == SURVIVAL || this == ADVENTURE || this == NEWMODE;
}
NEWMODE - имя режима, которое мы вписывали тут
4. Добавляем наш режим в создание мира (в меню)
4.1 Открываем файл GuiCreateWorld.java
4.2 Ищем строки:
else if (this.gameMode.equals("hardcore"))
{
if (!this.field_73935_p)
{
this.field_73926_o = true;
}
this.field_73933_r = false;
this.gameMode = "creative";
this.func_73914_h();
this.field_73933_r = false;
this.field_73936_z.enabled = true;
this.field_73938_x.enabled = true;
}
4.3 Добавляем ниже:
else if (this.gameMode.equals("creative"))
{
if (!this.field_73935_p)
{
this.field_73926_o = true;
}
this.field_73933_r = false;
this.gameMode = "newmode";
this.func_73914_h();
this.field_73933_r = false;
this.field_73936_z.enabled = true;
this.field_73938_x.enabled = true;
}
creative - после какого режима будет показываться наш режим
newmode - имя нашего режима игры
4.4 Открываем файл GuiSelectWorld.java
4.5 Ищем строку:
private String[] localizedGameModeText = new String[3];
И меняем цифру 3 на 4, так как нумирация идёт с нуля, и получается 4 режима игры
this.localizedGameModeText[EnumGameType.ADVENTURE.getID()] = var1.translateKey("gameMode.adventure");
4.7 Добавляем ниже наш новый режим
this.localizedGameModeText[EnumGameType.NEWMODE.getID()] = var1.translateKey("gameMode.newmode");
NEWMODE - имя режима, которое мы вписывали тут
5. Добавляем название режима и описание в lang файл
5.1 Открываем файл ru_RU.lang
5.2 Ищем строку:
gameMode.hardcore=Хардкор!
5.3 Добавляем ниже:
gameMode.newmode=Новый режим
Добавляем описание режима
5.4 Ищем строку
selectWorld.gameMode.hardcore.line2=сложностью и только одной жизнью
5.5 Добавляем ниже:
selectWorld.gameMode.newmode=Новый режим
selectWorld.gameMode.newmode.line1=Описание 1
selectWorld.gameMode.newmode.line2=описание 2
Всё, если Вы всё сделали правильно, то при создании мира, можно выбрать наш режим
И после перезахода в игру, ваш сохранённый мир будет показан
1.1 Ищем строку:
ADVENTURE(2, "adventure"),
1.2 Добавляем, после:
NEWMODE(3, "newmode");
newmode - имя нашего режима игры
1.3 Ищем строки:
public void configurePlayerCapabilities(PlayerCapabilities par1PlayerCapabilities)
{
if (this == CREATIVE)
{
par1PlayerCapabilities.allowFlying = true;
par1PlayerCapabilities.isCreativeMode = true;
par1PlayerCapabilities.disableDamage = true;
}
else
{
par1PlayerCapabilities.allowFlying = false;
par1PlayerCapabilities.isCreativeMode = false;
par1PlayerCapabilities.disableDamage = false;
par1PlayerCapabilities.isFlying = false;
}
par1PlayerCapabilities.allowEdit = !this.isAdventure();
}
1.4 Заменяем на:
public void configurePlayerCapabilities(PlayerCapabilities par1PlayerCapabilities)
{
if (this == CREATIVE)
{
par1PlayerCapabilities.allowFlying = true;
par1PlayerCapabilities.isCreativeMode = true;
par1PlayerCapabilities.disableDamage = true;
}
else if(this == SURVIVAL)
{
par1PlayerCapabilities.allowFlying = false;
par1PlayerCapabilities.isCreativeMode = false;
par1PlayerCapabilities.disableDamage = false;
par1PlayerCapabilities.isFlying = false;
}
else if(this == NEWMODE)
{
par1PlayerCapabilities.allowFlying = false; //разрешаем/запрещаем игроку летать по двойному прыжку
par1PlayerCapabilities.isCreativeMode = false; //если у нас режим, похожий на креатив, то пишем true, если же нет - false
par1PlayerCapabilities.disableDamage = true; //вклчюаем/отключаем получение урона
par1PlayerCapabilities.isFlying = false;
}
par1PlayerCapabilities.allowEdit = !this.isAdventure();
}
NEWMODE - имя режима, которое мы вписывали тут
1.2 Добавляем, после:
NEWMODE(3, "newmode");
2. Делаем подобие инвентаря как в "креативе"
2.1 Для того, что бы сделать инвентарь как в креативе, надо найти строки:
public boolean isCreative()
{
return this == CREATIVE;
}
2.2 И приписать наш новый режим вот таким образом:
public boolean isCreative()
{
return this == CREATIVE || this == NEWMODE;
}
NEWMODE - имя режима, которое мы вписывали тут
1.2 Добавляем, после:
NEWMODE(3, "newmode");
3. Делаем подобие инвентаря как в "выживании"
3.1 Для того, что бы сделать инвентарь как в выживании, надо найти строки:
public boolean func_77144_e()
{
return this == SURVIVAL || this == ADVENTURE;
}
3.2 И приписать наш новый режим вот таким образом:
public boolean func_77144_e()
{
return this == SURVIVAL || this == ADVENTURE || this == NEWMODE;
}
NEWMODE - имя режима, которое мы вписывали тут
1.2 Добавляем, после:
NEWMODE(3, "newmode");
4. Добавляем наш режим в создание мира (в меню)
4.1 Открываем файл GuiCreateWorld.java
4.2 Ищем строки:
else if (this.gameMode.equals("hardcore"))
{
if (!this.field_73935_p)
{
this.field_73926_o = true;
}
this.field_73933_r = false;
this.gameMode = "creative";
this.func_73914_h();
this.field_73933_r = false;
this.field_73936_z.enabled = true;
this.field_73938_x.enabled = true;
}
4.3 Добавляем ниже:
else if (this.gameMode.equals("creative"))
{
if (!this.field_73935_p)
{
this.field_73926_o = true;
}
this.field_73933_r = false;
this.gameMode = "newmode";
this.func_73914_h();
this.field_73933_r = false;
this.field_73936_z.enabled = true;
this.field_73938_x.enabled = true;
}
creative - после какого режима будет показываться наш режим
newmode - имя нашего режима игры
4.4 Открываем файл GuiSelectWorld.java
4.5 Ищем строку:
private String[] localizedGameModeText = new String[3];
И меняем цифру 3 на 4, так как нумирация идёт с нуля, и получается 4 режима игры
4.6 Ищем строку:NOT_SET(-1, ""),
SURVIVAL(0, "survival"),
CREATIVE(1, "creative"),
ADVENTURE(2, "adventure"),
NEWMODE(3, "newmode");
this.localizedGameModeText[EnumGameType.ADVENTURE.getID()] = var1.translateKey("gameMode.adventure");
4.7 Добавляем ниже наш новый режим
this.localizedGameModeText[EnumGameType.NEWMODE.getID()] = var1.translateKey("gameMode.newmode");
NEWMODE - имя режима, которое мы вписывали тут
1.2 Добавляем, после:
NEWMODE(3, "newmode");
5. Добавляем название режима и описание в lang файл
5.1 Открываем файл ru_RU.lang
5.2 Ищем строку:
gameMode.hardcore=Хардкор!
5.3 Добавляем ниже:
gameMode.newmode=Новый режим
Добавляем описание режима
5.4 Ищем строку
selectWorld.gameMode.hardcore.line2=сложностью и только одной жизнью
5.5 Добавляем ниже:
selectWorld.gameMode.newmode=Новый режим
selectWorld.gameMode.newmode.line1=Описание 1
selectWorld.gameMode.newmode.line2=описание 2
Всё, если Вы всё сделали правильно, то при создании мира, можно выбрать наш режим

И после перезахода в игру, ваш сохранённый мир будет показан

17. Создание своей (новой) жидкости (1.3.2) (Добавлено)
1. Открываем файл Block.java
2. Добавляем новый блок
public static final Block newFluidMoving = (new BlockNewFlowingFluid(160, Material.water)).setHardness(100.0F).setLightOpacity(3).setBlockName("new").setCreativeTab(CreativeTabs.tabBlock).disableStats().setRequiresSelfNotify();
public static final Block newFluidStill = (new BlockNewStationaryFluid(161, Material.water)).setHardness(100.0F).setLightOpacity(3).setBlockName("new").setCreativeTab(CreativeTabs.tabBlock).disableStats().setRequiresSelfNotify();
3. Создаём новые файлы
3.1. BlockNewFlowingFluid.java (текучая жидкость)
package net.minecraft.src;
import java.util.Random;
public class BlockNewFlowingFluid extends BlockFluid
{
/**
* Number of horizontally adjacent liquid source blocks. Diagonal doesn't count. Only source blocks of the same
* liquid as the block using the field are counted.
*/
int numAdjacentSources;
boolean isOptimalFlowDirection[];
int flowCost[];
protected BlockNewFlowingFluid(int par1, Material par2Material)
{
super(par1, par2Material);
numAdjacentSources = 0;
isOptimalFlowDirection = new boolean[4];
flowCost = new int[4];
}
/**
* Цвет жидкости
*/
public int colorMultiplier(IBlockAccess iblockaccess, int i, int j, int k)
{
return 0xFF6666;
}
/**
* Updates the flow for the BlockFlowing object.
*/
private void updateFlow(World par1World, int par2, int par3, int par4)
{
int i = par1World.getBlockMetadata(par2, par3, par4);
par1World.setBlockAndMetadata(par2, par3, par4, blockID + 1, i);
par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4);
par1World.markBlockNeedsUpdate(par2, par3, par4);
}
public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{
return blockMaterial != Material.lava;
}
/**
* Ticks the block if it's been scheduled
*/
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
{
int var6 = this.getFlowDecay(par1World, par2, par3, par4);
byte var7 = 1;
if (this.blockMaterial == Material.lava && !par1World.provider.isHellWorld)
{
var7 = 2;
}
boolean var8 = true;
int var10;
if (var6 > 0)
{
byte var9 = -100;
this.numAdjacentSources = 0;
int var12 = this.getSmallestFlowDecay(par1World, par2 - 1, par3, par4, var9);
var12 = this.getSmallestFlowDecay(par1World, par2 + 1, par3, par4, var12);
var12 = this.getSmallestFlowDecay(par1World, par2, par3, par4 - 1, var12);
var12 = this.getSmallestFlowDecay(par1World, par2, par3, par4 + 1, var12);
var10 = var12 + var7;
if (var10 >= 8 || var12 < 0)
{
var10 = -1;
}
if (this.getFlowDecay(par1World, par2, par3 + 1, par4) >= 0)
{
int var11 = this.getFlowDecay(par1World, par2, par3 + 1, par4);
if (var11 >= 8)
{
var10 = var11;
}
else
{
var10 = var11 + 8;
}
}
if (this.numAdjacentSources >= 2 && this.blockMaterial == Material.water)
{
if (par1World.getBlockMaterial(par2, par3 - 1, par4).isSolid())
{
var10 = 0;
}
else if (par1World.getBlockMaterial(par2, par3 - 1, par4) == this.blockMaterial && par1World.getBlockMetadata(par2, par3, par4) == 0)
{
var10 = 0;
}
}
if (this.blockMaterial == Material.lava && var6 < 8 && var10 < 8 && var10 > var6 && par5Random.nextInt(4) != 0)
{
var10 = var6;
var8 = false;
}
if (var10 == var6)
{
if (var8)
{
this.updateFlow(par1World, par2, par3, par4);
}
}
else
{
var6 = var10;
if (var10 < 0)
{
par1World.setBlockWithNotify(par2, par3, par4, 0);
}
else
{
par1World.setBlockMetadataWithNotify(par2, par3, par4, var10);
par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate());
par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
}
}
}
else
{
this.updateFlow(par1World, par2, par3, par4);
}
if (this.liquidCanDisplaceBlock(par1World, par2, par3 - 1, par4))
{
if (this.blockMaterial == Material.lava && par1World.getBlockMaterial(par2, par3 - 1, par4) == Material.water)
{
par1World.setBlockWithNotify(par2, par3 - 1, par4, Block.stone.blockID);
this.triggerLavaMixEffects(par1World, par2, par3 - 1, par4);
return;
}
if (var6 >= 8)
{
this.flowIntoBlock(par1World, par2, par3 - 1, par4, var6);
}
else
{
this.flowIntoBlock(par1World, par2, par3 - 1, par4, var6 + 8);
}
}
else if (var6 >= 0 && (var6 == 0 || this.blockBlocksFlow(par1World, par2, par3 - 1, par4)))
{
boolean[] var13 = this.getOptimalFlowDirections(par1World, par2, par3, par4);
var10 = var6 + var7;
if (var6 >= 8)
{
var10 = 1;
}
if (var10 >= 8)
{
return;
}
if (var13[0])
{
this.flowIntoBlock(par1World, par2 - 1, par3, par4, var10);
}
if (var13[1])
{
this.flowIntoBlock(par1World, par2 + 1, par3, par4, var10);
}
if (var13[2])
{
this.flowIntoBlock(par1World, par2, par3, par4 - 1, var10);
}
if (var13[3])
{
this.flowIntoBlock(par1World, par2, par3, par4 + 1, var10);
}
}
}
/**
* flowIntoBlock(World world, int x, int y, int z, int newFlowDecay) - Flows into the block at the coordinates and
* changes the block type to the liquid.
*/
private void flowIntoBlock(World par1World, int par2, int par3, int par4, int par5)
{
if (liquidCanDisplaceBlock(par1World, par2, par3, par4))
{
int i = par1World.getBlockId(par2, par3, par4);
if (i > 0)
{
if (blockMaterial == Material.lava)
{
triggerLavaMixEffects(par1World, par2, par3, par4);
}
else
{
Block.blocksList.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
}
}
par1World.setBlockAndMetadataWithNotify(par2, par3, par4, blockID, par5);
}
}
/**
* calculateFlowCost(World world, int x, int y, int z, int accumulatedCost, int previousDirectionOfFlow) - Used to
* determine the path of least resistance, this method returns the lowest possible flow cost for the direction of
* flow indicated. Each necessary horizontal flow adds to the flow cost.
*/
private int calculateFlowCost(World par1World, int par2, int par3, int par4, int par5, int par6)
{
int i = 1000;
for (int j = 0; j < 4; j++)
{
if (j == 0 && par6 == 1 || j == 1 && par6 == 0 || j == 2 && par6 == 3 || j == 3 && par6 == 2)
{
continue;
}
int k = par2;
int l = par3;
int i1 = par4;
if (j == 0)
{
k--;
}
if (j == 1)
{
k++;
}
if (j == 2)
{
i1--;
}
if (j == 3)
{
i1++;
}
if (blockBlocksFlow(par1World, k, l, i1) || par1World.getBlockMaterial(k, l, i1) == blockMaterial && par1World.getBlockMetadata(k, l, i1) == 0)
{
continue;
}
if (!blockBlocksFlow(par1World, k, l - 1, i1))
{
return par5;
}
if (par5 >= 4)
{
continue;
}
int j1 = calculateFlowCost(par1World, k, l, i1, par5 + 1, j);
if (j1 < i)
{
i = j1;
}
}
return i;
}
/**
* Returns a boolean array indicating which flow directions are optimal based on each direction's calculated flow
* cost. Each array index corresponds to one of the four cardinal directions. A value of true indicates the
* direction is optimal.
*/
private boolean[] getOptimalFlowDirections(World par1World, int par2, int par3, int par4)
{
for (int i = 0; i < 4; i++)
{
flowCost = 1000;
int k = par2;
int j1 = par3;
int k1 = par4;
if (i == 0)
{
k--;
}
if (i == 1)
{
k++;
}
if (i == 2)
{
k1--;
}
if (i == 3)
{
k1++;
}
if (blockBlocksFlow(par1World, k, j1, k1) || par1World.getBlockMaterial(k, j1, k1) == blockMaterial && par1World.getBlockMetadata(k, j1, k1) == 0)
{
continue;
}
if (!blockBlocksFlow(par1World, k, j1 - 1, k1))
{
flowCost = 0;
}
else
{
flowCost = calculateFlowCost(par1World, k, j1, k1, 1, i);
}
}
int j = flowCost[0];
for (int l = 1; l < 4; l++)
{
if (flowCost[l] < j)
{
j = flowCost[l];
}
}
for (int i1 = 0; i1 < 4; i1++)
{
isOptimalFlowDirection[i1] = flowCost[i1] == j;
}
return isOptimalFlowDirection;
}
/**
* Returns true if block at coords blocks fluids
*/
//Думаю тут понятно.
private boolean blockBlocksFlow(World par1World, int par2, int par3, int par4)
{
int i = par1World.getBlockId(par2, par3, par4);
if (i == Block.doorWood.blockID || i == Block.doorSteel.blockID || i == Block.signPost.blockID || i == Block.ladder.blockID || i == Block.reed.blockID)
{
return true;
}
if (i == 0)
{
return false;
}
Material material = Block.blocksList.blockMaterial;
if (material == Material.portal)
{
return true;
}
return material.blocksMovement();
}
/**
* getSmallestFlowDecay(World world, intx, int y, int z, int currentSmallestFlowDecay) - Looks up the flow decay at
* the coordinates given and returns the smaller of this value or the provided currentSmallestFlowDecay. If one
* value is valid and the other isn't, the valid value will be returned. Valid values are >= 0. Flow decay is the
* amount that a liquid has dissipated. 0 indicates a source block.
*/
protected int getSmallestFlowDecay(World par1World, int par2, int par3, int par4, int par5)
{
int i = getFlowDecay(par1World, par2, par3, par4);
if (i < 0)
{
return par5;
}
if (i == 0)
{
numAdjacentSources++;
}
if (i >= 8)
{
i = 0;
}
return par5 >= 0 && i >= par5 ? par5 : i;
}
/**
* Returns true if the block at the coordinates can be displaced by the liquid.
*/
private boolean liquidCanDisplaceBlock(World par1World, int par2, int par3, int par4)
{
Material material = par1World.getBlockMaterial(par2, par3, par4);
if (material == blockMaterial)
{
return false;
}
if (material == Material.lava)
{
return false;
}
else
{
return !blockBlocksFlow(par1World, par2, par3, par4);
}
}
/**
* Called whenever the block is added into the world. Args: world, x, y, z
*/
public void onBlockAdded(World par1World, int par2, int par3, int par4)
{
super.onBlockAdded(par1World, par2, par3, par4);
if (par1World.getBlockId(par2, par3, par4) == blockID)
{
par1World.scheduleBlockUpdate(par2, par3, par4, blockID, tickRate());
}
}
}
3.2. BlockNewStationaryFluid.java (стоячая жидкость)
package net.minecraft.src;
import java.util.Random;
public class BlockNewStationaryFluid extends BlockFluid
{
protected BlockNewStationaryFluid(int par1, Material par2Material)
{
super(par1, par2Material);
setTickRandomly(false);
if (par2Material == Material.lava)
{
setTickRandomly(true);
}
}
/**
* Цвет жидкости
*/
public int colorMultiplier(IBlockAccess iblockaccess, int i, int j, int k)
{
return 0xFF6666;
}
public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{
return blockMaterial != Material.lava;
}
/**
* Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
* their own) Args: x, y, z, neighbor blockID
*/
public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
{
super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
if (par1World.getBlockId(par2, par3, par4) == blockID)
{
setNotStationary(par1World, par2, par3, par4);
}
}
/**
* Changes the block ID to that of an updating fluid.
*/
private void setNotStationary(World par1World, int par2, int par3, int par4)
{
int i = par1World.getBlockMetadata(par2, par3, par4);
par1World.editingBlocks = true;
par1World.setBlockAndMetadata(par2, par3, par4, blockID - 1, i);
par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4);
par1World.scheduleBlockUpdate(par2, par3, par4, blockID - 1, tickRate());
par1World.editingBlocks = false;
}
/**
* Ticks the block if it's been scheduled
*/
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
{
if (blockMaterial == Material.lava)
{
int i = par5Random.nextInt(3);
for (int j = 0; j < i; j++)
{
par2 += par5Random.nextInt(3) - 1;
par3++;
par4 += par5Random.nextInt(3) - 1;
int l = par1World.getBlockId(par2, par3, par4);
if (l == 0)
{
if (isFlammable(par1World, par2 - 1, par3, par4) || isFlammable(par1World, par2 + 1, par3, par4) || isFlammable(par1World, par2, par3, par4 - 1) || isFlammable(par1World, par2, par3, par4 + 1) || isFlammable(par1World, par2, par3 - 1, par4) || isFlammable(par1World, par2, par3 + 1, par4))
{
par1World.setBlockWithNotify(par2, par3, par4, Block.fire.blockID);
return;
}
continue;
}
if (Block.blocksList[l].blockMaterial.blocksMovement())
{
return;
}
}
if (i == 0)
{
int k = par2;
int i1 = par4;
for (int j1 = 0; j1 < 3; j1++)
{
par2 = (k + par5Random.nextInt(3)) - 1;
par4 = (i1 + par5Random.nextInt(3)) - 1;
if (par1World.isAirBlock(par2, par3 + 1, par4) && isFlammable(par1World, par2, par3, par4))
{
par1World.setBlockWithNotify(par2, par3 + 1, par4, Block.fire.blockID);
}
}
}
}
}
/**
* Checks to see if the block is flammable.
*/
private boolean isFlammable(World par1World, int par2, int par3, int par4)
{
return par1World.getBlockMaterial(par2, par3, par4).getCanBurn();
}
}
2. Добавляем новый блок
public static final Block newFluidMoving = (new BlockNewFlowingFluid(160, Material.water)).setHardness(100.0F).setLightOpacity(3).setBlockName("new").setCreativeTab(CreativeTabs.tabBlock).disableStats().setRequiresSelfNotify();
public static final Block newFluidStill = (new BlockNewStationaryFluid(161, Material.water)).setHardness(100.0F).setLightOpacity(3).setBlockName("new").setCreativeTab(CreativeTabs.tabBlock).disableStats().setRequiresSelfNotify();
3. Создаём новые файлы
3.1. BlockNewFlowingFluid.java (текучая жидкость)
package net.minecraft.src;
import java.util.Random;
public class BlockNewFlowingFluid extends BlockFluid
{
/**
* Number of horizontally adjacent liquid source blocks. Diagonal doesn't count. Only source blocks of the same
* liquid as the block using the field are counted.
*/
int numAdjacentSources;
boolean isOptimalFlowDirection[];
int flowCost[];
protected BlockNewFlowingFluid(int par1, Material par2Material)
{
super(par1, par2Material);
numAdjacentSources = 0;
isOptimalFlowDirection = new boolean[4];
flowCost = new int[4];
}
/**
* Цвет жидкости
*/
public int colorMultiplier(IBlockAccess iblockaccess, int i, int j, int k)
{
return 0xFF6666;
}
/**
* Updates the flow for the BlockFlowing object.
*/
private void updateFlow(World par1World, int par2, int par3, int par4)
{
int i = par1World.getBlockMetadata(par2, par3, par4);
par1World.setBlockAndMetadata(par2, par3, par4, blockID + 1, i);
par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4);
par1World.markBlockNeedsUpdate(par2, par3, par4);
}
public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{
return blockMaterial != Material.lava;
}
/**
* Ticks the block if it's been scheduled
*/
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
{
int var6 = this.getFlowDecay(par1World, par2, par3, par4);
byte var7 = 1;
if (this.blockMaterial == Material.lava && !par1World.provider.isHellWorld)
{
var7 = 2;
}
boolean var8 = true;
int var10;
if (var6 > 0)
{
byte var9 = -100;
this.numAdjacentSources = 0;
int var12 = this.getSmallestFlowDecay(par1World, par2 - 1, par3, par4, var9);
var12 = this.getSmallestFlowDecay(par1World, par2 + 1, par3, par4, var12);
var12 = this.getSmallestFlowDecay(par1World, par2, par3, par4 - 1, var12);
var12 = this.getSmallestFlowDecay(par1World, par2, par3, par4 + 1, var12);
var10 = var12 + var7;
if (var10 >= 8 || var12 < 0)
{
var10 = -1;
}
if (this.getFlowDecay(par1World, par2, par3 + 1, par4) >= 0)
{
int var11 = this.getFlowDecay(par1World, par2, par3 + 1, par4);
if (var11 >= 8)
{
var10 = var11;
}
else
{
var10 = var11 + 8;
}
}
if (this.numAdjacentSources >= 2 && this.blockMaterial == Material.water)
{
if (par1World.getBlockMaterial(par2, par3 - 1, par4).isSolid())
{
var10 = 0;
}
else if (par1World.getBlockMaterial(par2, par3 - 1, par4) == this.blockMaterial && par1World.getBlockMetadata(par2, par3, par4) == 0)
{
var10 = 0;
}
}
if (this.blockMaterial == Material.lava && var6 < 8 && var10 < 8 && var10 > var6 && par5Random.nextInt(4) != 0)
{
var10 = var6;
var8 = false;
}
if (var10 == var6)
{
if (var8)
{
this.updateFlow(par1World, par2, par3, par4);
}
}
else
{
var6 = var10;
if (var10 < 0)
{
par1World.setBlockWithNotify(par2, par3, par4, 0);
}
else
{
par1World.setBlockMetadataWithNotify(par2, par3, par4, var10);
par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate());
par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
}
}
}
else
{
this.updateFlow(par1World, par2, par3, par4);
}
if (this.liquidCanDisplaceBlock(par1World, par2, par3 - 1, par4))
{
if (this.blockMaterial == Material.lava && par1World.getBlockMaterial(par2, par3 - 1, par4) == Material.water)
{
par1World.setBlockWithNotify(par2, par3 - 1, par4, Block.stone.blockID);
this.triggerLavaMixEffects(par1World, par2, par3 - 1, par4);
return;
}
if (var6 >= 8)
{
this.flowIntoBlock(par1World, par2, par3 - 1, par4, var6);
}
else
{
this.flowIntoBlock(par1World, par2, par3 - 1, par4, var6 + 8);
}
}
else if (var6 >= 0 && (var6 == 0 || this.blockBlocksFlow(par1World, par2, par3 - 1, par4)))
{
boolean[] var13 = this.getOptimalFlowDirections(par1World, par2, par3, par4);
var10 = var6 + var7;
if (var6 >= 8)
{
var10 = 1;
}
if (var10 >= 8)
{
return;
}
if (var13[0])
{
this.flowIntoBlock(par1World, par2 - 1, par3, par4, var10);
}
if (var13[1])
{
this.flowIntoBlock(par1World, par2 + 1, par3, par4, var10);
}
if (var13[2])
{
this.flowIntoBlock(par1World, par2, par3, par4 - 1, var10);
}
if (var13[3])
{
this.flowIntoBlock(par1World, par2, par3, par4 + 1, var10);
}
}
}
/**
* flowIntoBlock(World world, int x, int y, int z, int newFlowDecay) - Flows into the block at the coordinates and
* changes the block type to the liquid.
*/
private void flowIntoBlock(World par1World, int par2, int par3, int par4, int par5)
{
if (liquidCanDisplaceBlock(par1World, par2, par3, par4))
{
int i = par1World.getBlockId(par2, par3, par4);
if (i > 0)
{
if (blockMaterial == Material.lava)
{
triggerLavaMixEffects(par1World, par2, par3, par4);
}
else
{
Block.blocksList.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
}
}
par1World.setBlockAndMetadataWithNotify(par2, par3, par4, blockID, par5);
}
}
/**
* calculateFlowCost(World world, int x, int y, int z, int accumulatedCost, int previousDirectionOfFlow) - Used to
* determine the path of least resistance, this method returns the lowest possible flow cost for the direction of
* flow indicated. Each necessary horizontal flow adds to the flow cost.
*/
private int calculateFlowCost(World par1World, int par2, int par3, int par4, int par5, int par6)
{
int i = 1000;
for (int j = 0; j < 4; j++)
{
if (j == 0 && par6 == 1 || j == 1 && par6 == 0 || j == 2 && par6 == 3 || j == 3 && par6 == 2)
{
continue;
}
int k = par2;
int l = par3;
int i1 = par4;
if (j == 0)
{
k--;
}
if (j == 1)
{
k++;
}
if (j == 2)
{
i1--;
}
if (j == 3)
{
i1++;
}
if (blockBlocksFlow(par1World, k, l, i1) || par1World.getBlockMaterial(k, l, i1) == blockMaterial && par1World.getBlockMetadata(k, l, i1) == 0)
{
continue;
}
if (!blockBlocksFlow(par1World, k, l - 1, i1))
{
return par5;
}
if (par5 >= 4)
{
continue;
}
int j1 = calculateFlowCost(par1World, k, l, i1, par5 + 1, j);
if (j1 < i)
{
i = j1;
}
}
return i;
}
/**
* Returns a boolean array indicating which flow directions are optimal based on each direction's calculated flow
* cost. Each array index corresponds to one of the four cardinal directions. A value of true indicates the
* direction is optimal.
*/
private boolean[] getOptimalFlowDirections(World par1World, int par2, int par3, int par4)
{
for (int i = 0; i < 4; i++)
{
flowCost = 1000;
int k = par2;
int j1 = par3;
int k1 = par4;
if (i == 0)
{
k--;
}
if (i == 1)
{
k++;
}
if (i == 2)
{
k1--;
}
if (i == 3)
{
k1++;
}
if (blockBlocksFlow(par1World, k, j1, k1) || par1World.getBlockMaterial(k, j1, k1) == blockMaterial && par1World.getBlockMetadata(k, j1, k1) == 0)
{
continue;
}
if (!blockBlocksFlow(par1World, k, j1 - 1, k1))
{
flowCost = 0;
}
else
{
flowCost = calculateFlowCost(par1World, k, j1, k1, 1, i);
}
}
int j = flowCost[0];
for (int l = 1; l < 4; l++)
{
if (flowCost[l] < j)
{
j = flowCost[l];
}
}
for (int i1 = 0; i1 < 4; i1++)
{
isOptimalFlowDirection[i1] = flowCost[i1] == j;
}
return isOptimalFlowDirection;
}
/**
* Returns true if block at coords blocks fluids
*/
//Думаю тут понятно.
private boolean blockBlocksFlow(World par1World, int par2, int par3, int par4)
{
int i = par1World.getBlockId(par2, par3, par4);
if (i == Block.doorWood.blockID || i == Block.doorSteel.blockID || i == Block.signPost.blockID || i == Block.ladder.blockID || i == Block.reed.blockID)
{
return true;
}
if (i == 0)
{
return false;
}
Material material = Block.blocksList.blockMaterial;
if (material == Material.portal)
{
return true;
}
return material.blocksMovement();
}
/**
* getSmallestFlowDecay(World world, intx, int y, int z, int currentSmallestFlowDecay) - Looks up the flow decay at
* the coordinates given and returns the smaller of this value or the provided currentSmallestFlowDecay. If one
* value is valid and the other isn't, the valid value will be returned. Valid values are >= 0. Flow decay is the
* amount that a liquid has dissipated. 0 indicates a source block.
*/
protected int getSmallestFlowDecay(World par1World, int par2, int par3, int par4, int par5)
{
int i = getFlowDecay(par1World, par2, par3, par4);
if (i < 0)
{
return par5;
}
if (i == 0)
{
numAdjacentSources++;
}
if (i >= 8)
{
i = 0;
}
return par5 >= 0 && i >= par5 ? par5 : i;
}
/**
* Returns true if the block at the coordinates can be displaced by the liquid.
*/
private boolean liquidCanDisplaceBlock(World par1World, int par2, int par3, int par4)
{
Material material = par1World.getBlockMaterial(par2, par3, par4);
if (material == blockMaterial)
{
return false;
}
if (material == Material.lava)
{
return false;
}
else
{
return !blockBlocksFlow(par1World, par2, par3, par4);
}
}
/**
* Called whenever the block is added into the world. Args: world, x, y, z
*/
public void onBlockAdded(World par1World, int par2, int par3, int par4)
{
super.onBlockAdded(par1World, par2, par3, par4);
if (par1World.getBlockId(par2, par3, par4) == blockID)
{
par1World.scheduleBlockUpdate(par2, par3, par4, blockID, tickRate());
}
}
}
3.2. BlockNewStationaryFluid.java (стоячая жидкость)
package net.minecraft.src;
import java.util.Random;
public class BlockNewStationaryFluid extends BlockFluid
{
protected BlockNewStationaryFluid(int par1, Material par2Material)
{
super(par1, par2Material);
setTickRandomly(false);
if (par2Material == Material.lava)
{
setTickRandomly(true);
}
}
/**
* Цвет жидкости
*/
public int colorMultiplier(IBlockAccess iblockaccess, int i, int j, int k)
{
return 0xFF6666;
}
public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{
return blockMaterial != Material.lava;
}
/**
* Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
* their own) Args: x, y, z, neighbor blockID
*/
public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
{
super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
if (par1World.getBlockId(par2, par3, par4) == blockID)
{
setNotStationary(par1World, par2, par3, par4);
}
}
/**
* Changes the block ID to that of an updating fluid.
*/
private void setNotStationary(World par1World, int par2, int par3, int par4)
{
int i = par1World.getBlockMetadata(par2, par3, par4);
par1World.editingBlocks = true;
par1World.setBlockAndMetadata(par2, par3, par4, blockID - 1, i);
par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4);
par1World.scheduleBlockUpdate(par2, par3, par4, blockID - 1, tickRate());
par1World.editingBlocks = false;
}
/**
* Ticks the block if it's been scheduled
*/
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
{
if (blockMaterial == Material.lava)
{
int i = par5Random.nextInt(3);
for (int j = 0; j < i; j++)
{
par2 += par5Random.nextInt(3) - 1;
par3++;
par4 += par5Random.nextInt(3) - 1;
int l = par1World.getBlockId(par2, par3, par4);
if (l == 0)
{
if (isFlammable(par1World, par2 - 1, par3, par4) || isFlammable(par1World, par2 + 1, par3, par4) || isFlammable(par1World, par2, par3, par4 - 1) || isFlammable(par1World, par2, par3, par4 + 1) || isFlammable(par1World, par2, par3 - 1, par4) || isFlammable(par1World, par2, par3 + 1, par4))
{
par1World.setBlockWithNotify(par2, par3, par4, Block.fire.blockID);
return;
}
continue;
}
if (Block.blocksList[l].blockMaterial.blocksMovement())
{
return;
}
}
if (i == 0)
{
int k = par2;
int i1 = par4;
for (int j1 = 0; j1 < 3; j1++)
{
par2 = (k + par5Random.nextInt(3)) - 1;
par4 = (i1 + par5Random.nextInt(3)) - 1;
if (par1World.isAirBlock(par2, par3 + 1, par4) && isFlammable(par1World, par2, par3, par4))
{
par1World.setBlockWithNotify(par2, par3 + 1, par4, Block.fire.blockID);
}
}
}
}
}
/**
* Checks to see if the block is flammable.
*/
private boolean isFlammable(World par1World, int par2, int par3, int par4)
{
return par1World.getBlockMaterial(par2, par3, par4).getCanBurn();
}
}
1. Запрещаем просмотр мира сквозь блок (как X-Ray)
2. Добавляем атаку игрока при соприкосновении с блоком
3. Добавляем разные текстуры на разные поверхности блоков
4. Делаем блок "проходимым"
Добавляем в файл блока перед последней скобкой данный код
public boolean isOpaqueCube()
{
return false;
}
public boolean isOpaqueCube()
{
return false;
}
public void onEntityCollidedWithBlock(World par1World, int x, int y, int z, Entity par5Entity)
{
par5Entity.attackEntityFrom(DamageSource.cactus, 1);
}
{
par5Entity.attackEntityFrom(DamageSource.cactus, 1);
}
1. Когда мы создаём блок, мы указываем основную текстуру блока, к примеру
(new BlockNew(46, 8))
8 - текстура блока (в нашем случаем мы указали переднюю текстуру блока)
2. Открываем файл самого блока, и добавляем
public int getBlockTextureFromSide(int par1)
{
return par1 == 0 ? this.blockIndexInTexture + 2 : (par1 == 1 ? this.blockIndexInTexture + 1 : this.blockIndexInTexture);
}
this.blockIndexInTexture + 2 - текстура нижней части блока (то есть мы к 8-ой текстуре прибавляем 2 и получаем 10-ую текстуру. Значит текстура, которая идёт по счёту 10-ой - становится вниз блока)
this.blockIndexInTexture + 1 - текстура верхней части блока (так же как и с нижней частью, только прибавляем 1, а не 2. А значит текстура, которая идёт 9-ой становится на верх блока)
(new BlockNew(46, 8))
8 - текстура блока (в нашем случаем мы указали переднюю текстуру блока)
2. Открываем файл самого блока, и добавляем
public int getBlockTextureFromSide(int par1)
{
return par1 == 0 ? this.blockIndexInTexture + 2 : (par1 == 1 ? this.blockIndexInTexture + 1 : this.blockIndexInTexture);
}
this.blockIndexInTexture + 2 - текстура нижней части блока (то есть мы к 8-ой текстуре прибавляем 2 и получаем 10-ую текстуру. Значит текстура, которая идёт по счёту 10-ой - становится вниз блока)
this.blockIndexInTexture + 1 - текстура верхней части блока (так же как и с нижней частью, только прибавляем 1, а не 2. А значит текстура, которая идёт 9-ой становится на верх блока)
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int i)
{
return null;
}
{
return null;
}
Создание второго items.png (1.3.2)
1. Открываем файл RenderItem.java
1.1. Добавляем Иморты
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
1.2. Ищем строчки:
if (par3 < 256)
{
par2RenderEngine.bindTexture(par2RenderEngine.getTexture("/terrain.png"));
}
1.3. Добавляем после:
else if (Item.is2Item(par3))
{
par2RenderEngine.bindTexture(par2RenderEngine.getTexture("/gui/items-2.png"));
}
2. Открываем файл ItemRenderer.java
2.1. Добавляем Иморты
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
2.2. Ищем строчки:
if (var4 != null)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture("/terrain.png"));
}
2.3. Добавляем после:
else if (Item.is2Item(par2ItemStack.itemID))
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture("/gui/items-2.png"));
}
3. Открываем файл Item.java
3.1. Ищем:
public Item setTabToDisplayOn(CreativeTabs par1CreativeTabs)
{
this.field_77701_a = par1CreativeTabs;
return this;
}
3.2. Добавляем после:
public static boolean is2Item (int id)
{
return ((id >= 3000) && (id < 3257));
}
Теперь предметы с ID от 3000 до 3256 будут использовать Items-2.png
Сам файл items-2.png должен находится по этому пути: minecraft.jar/gui/items-2.png
1.1. Добавляем Иморты
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
1.2. Ищем строчки:
if (par3 < 256)
{
par2RenderEngine.bindTexture(par2RenderEngine.getTexture("/terrain.png"));
}
1.3. Добавляем после:
else if (Item.is2Item(par3))
{
par2RenderEngine.bindTexture(par2RenderEngine.getTexture("/gui/items-2.png"));
}
2. Открываем файл ItemRenderer.java
2.1. Добавляем Иморты
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
2.2. Ищем строчки:
if (var4 != null)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture("/terrain.png"));
}
2.3. Добавляем после:
else if (Item.is2Item(par2ItemStack.itemID))
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture("/gui/items-2.png"));
}
3. Открываем файл Item.java
3.1. Ищем:
public Item setTabToDisplayOn(CreativeTabs par1CreativeTabs)
{
this.field_77701_a = par1CreativeTabs;
return this;
}
3.2. Добавляем после:
public static boolean is2Item (int id)
{
return ((id >= 3000) && (id < 3257));
}
Теперь предметы с ID от 3000 до 3256 будут использовать Items-2.png
Сам файл items-2.png должен находится по этому пути: minecraft.jar/gui/items-2.png
Создание второго terrain.png (1.3.2) (доделано не до конца)
1. Открываем файл RenderItem.java
1.1. Добавляем Иморты
import net.minecraft.src.Block;
import net.minecraft.src.ItemStack;
1.2. Ищем строчки:
if (par3 < 256)
{
par2RenderEngine.bindTexture(par2RenderEngine.getTexture("/terrain.png"));
}
1.3. Добавляем после:
else if (Block.is2Block(par3))
{
par2RenderEngine.bindTexture(par2RenderEngine.getTexture("/terrain-2.png"));
}
2. Открываем файл ItemRenderer.java
2.1. Добавляем Иморты
import net.minecraft.src.Block;
import net.minecraft.src.ItemStack;
2.2. Ищем строчки:
if (var4 != null)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture("/terrain.png"));
}
2.3. Добавляем после:
else if (Block.is2Block(par2ItemStack.itemID))
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture("/terrain-2.png"));
}
3. Открываем файл Block.java
3.1. Ищем:
/**
* Called when the time changes.
*/
public void onTimeChanged(World par1World, long par2, long par4) {}
3.2. Добавляем после:
public static boolean is2Block(int id)
{
return ((id >= 160) && (id < 251));
}
Теперь блоки с ID от 150 до 250 будут использовать terrain-2.png
Сам файл terrain-2.png должен находится по этому пути: minecraft.jar/terrain-2.png
1.1. Добавляем Иморты
import net.minecraft.src.Block;
import net.minecraft.src.ItemStack;
1.2. Ищем строчки:
if (par3 < 256)
{
par2RenderEngine.bindTexture(par2RenderEngine.getTexture("/terrain.png"));
}
1.3. Добавляем после:
else if (Block.is2Block(par3))
{
par2RenderEngine.bindTexture(par2RenderEngine.getTexture("/terrain-2.png"));
}
2. Открываем файл ItemRenderer.java
2.1. Добавляем Иморты
import net.minecraft.src.Block;
import net.minecraft.src.ItemStack;
2.2. Ищем строчки:
if (var4 != null)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture("/terrain.png"));
}
2.3. Добавляем после:
else if (Block.is2Block(par2ItemStack.itemID))
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture("/terrain-2.png"));
}
3. Открываем файл Block.java
3.1. Ищем:
/**
* Called when the time changes.
*/
public void onTimeChanged(World par1World, long par2, long par4) {}
3.2. Добавляем после:
public static boolean is2Block(int id)
{
return ((id >= 160) && (id < 251));
}
Теперь блоки с ID от 150 до 250 будут использовать terrain-2.png
Сам файл terrain-2.png должен находится по этому пути: minecraft.jar/terrain-2.png
Получаем любую версию MineCraft
Я хочу вам рассказать о таком ресурсе внутреннего пользования как http://assets.minecraft.net/ (Официальный storage)
1. Открываем сайт
Получаем xml документ
2. Смотрим, какую версию вы хотите.
К примеру нам требуется скачать версию клиента (сервера) 1.4.7 (можете выбрать также любой пререлиз)
3. Открываем поиск, и ищем тег 1_4_7
На наш запрос обнаружилось 4 результата,
Первый - совсем для внутреннего пользования, пропускаем. а затем видим 3 тега:
1. Открываем сайт
Получаем xml документ
2. Смотрим, какую версию вы хотите.
К примеру нам требуется скачать версию клиента (сервера) 1.4.7 (можете выбрать также любой пререлиз)
3. Открываем поиск, и ищем тег 1_4_7
На наш запрос обнаружилось 4 результата,
Первый - совсем для внутреннего пользования, пропускаем. а затем видим 3 тега:
1_4_7/Minecraft_Server.exe
1_4_7/minecraft.jar
1_4_7/minecraft-server.jar
Знакомо? правильно - 2 - клиент, остальное - сервер.
Также мы видим метаинфу - размер и хэш файла.
4. Скачиваем нужную версию
Допустим возьмём клиент версии 1.4.7: дописываем к ссылке сайта
Ну и напоследок:
скажу что на сайте есть и другие "вкусности" например pe версия, а также файлы личного пользования(немногие, правда, запаролены).
Коды все рабочие и протестированные!

Отдельное спасибо:
FunnyAlien
blezigen - описание "Добавление имени блоку" и "Создание растения"
timkill - сборка моба из разных частей
_VlaDoS - создание брони и инструментов
ROBOCOP - описание категорий креатива
icool - добавление второго items.png
ROBOCOP - создание жидкости
cdkrot - скачиваем любую версию MineCraft
blezigen - описание "Добавление имени блоку" и "Создание растения"
timkill - сборка моба из разных частей
_VlaDoS - создание брони и инструментов
ROBOCOP - описание категорий креатива
icool - добавление второго items.png
ROBOCOP - создание жидкости
cdkrot - скачиваем любую версию MineCraft
P.S Тема будет пополняться со временем, так как я сначала делаю, потом выкладываю.
Не забываем удалить папку!
META-INFиз minecraft.jar
Если не удалите её, то будет много ошибок!
Важно!
"Большинство модов после этого изменения клиента (сервера) работать уже не будет"
и
"Если обновите клиент, то ваши модификации удалятся"
Автор - я. Копирование без размещения ссылки - запрещено.