Lekce 4 - Minecraft Modding - Solná hůlka a crafting
V předchozí lekci, Minecraft Modding - Konvence a SidedBlockTextures, jsme se naučili pravidla při ukládání tříd.
V tomto dílu bych rád udělal nějaký pořádný item, který už bude dokonce něco dělat (bude to solná hůlka, s kterou my budeme moci sníst jakýkoli block a doplní se nám hungerbar).
ItemSulWand
Jak jsem zmiňoval v minulém dílu, jelikož potřebujeme reagovat na nějaké eventy, je nutno vytvořit potomka třídy Item.
public class ItemSulWand extends Item{ public ItemSulWand(){ setUnlocalizedName("itemWand"); setCreativeTab(CreativeTabs.tabTools); setTextureName("sul_wand"); this.maxStackSize=1; this.setMaxDamage(32); } }
Zde bych mohl podotknout, že Minecraft uvidí tento item již jako nástroj, jelikož platí, že maxstacksize==1 a maxdamage > 0. To ale jen tak okrajově. Zatím jsme si udělali item, který se může poškodit 32krát a nelze ho stackovat. My ovšem chceme reagovat na event kliknutí pravým tlačítkem. Musíme tedy překrýt metodu onItemUse, která se zavolá vždy, když klikneme s tímto itemem v ruce na nějaký blok. V tomto případě vrací true, pokud tento item něco dělá.
/** java * @param itemstack s kterým klikám * @param player hráč, který itemstack drží * @param world svět * @param x coordináty bloku * @param y coordináty bloku * @param z coordináty bloku * @param side strana bloku, na kterou klikám * @param px coordináty kam přesně na tom bloku jsem klikl např doprostřed, vlevo dole...., rozsah 0.0-1.0 * @param py coordináty kam přesně na tom bloku jsem klikl * @param pz coordináty kam přesně na tom bloku jsem klikl */ @Override public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int side, float px, float py, float pz){ return true; }
Nu a teď si můžeme už hrát a dělat cokoliv co chceme. Pomocí parametru world můžeme přistupovat ke světu a tudíž i ke změně bloků. Na změnu bloku má World metodu setBlock(int x, int y, int z, Block block), kde xyz jsou souřadnice blocku a block, který na souřadnice chceme položit. Kdybych tuto metodu měl přiblížit vizuálně, v jedné chvíli by tam byl obsidian a vzápětí glass nebo air. Jenže to se nám nelíbí. My bychom chtěli aby tato změna blocku byla doprovázena nějakým efektem (např: Particles a zvuk rozbití). A proto je zde funkce func_147480_a(int x, int y, int z,boolean shouldDropAsItem), která má jako parametry souřadnice xyz a boolean jestli nám má vypadnout block, když ho zničíme. Ano, tato metoda má bohužel pěkně blbý název, ale důležité je, že nám rozbije block i s efektem. Dále je pak záhodno ošetřit nějaké výjimky, jako například abychom nemohli sníst bedrock. Ke zjištění na jaký block klikáme nám poslouží metoda getBlock().
if (world.getBlock(x, y, z)!=Blocks.bedrock){ world.func_147480_a(x,y,z,false); itemstack.damageItem(1, player); }
Nyní pokud klikneme pravým tlačítkem na jakýkoliv block kromě bedrocku, tak se nám zničí. Pomocí metody damageItem poškozujeme naši hůlku o 1 stupeň při každém snězení. (Když dojde výdrž hůlky, tak se nám zničí.)
player.getFoodStats().addStats(1,0.1F);
Postarali jsme se o nasycení hráče, kde jako 1. param je foodlevel a jako 2. je zde nasycenost (jak dlouho bude trvat než mu zase vyhládne).
player.playSound("random.burp", 1F, 1F);
A zde přehráváme hráči zvuk metodou playSound(String zvukName, float hlasitost, float rychlost_přehrání (větší než 1F bude zvuk zpomalen)). Seznam všech jmen zvuků je ke stáhnutí pod článkem.
Pokud si teď loadneme svět a zkusíme s naší hůlkou kliknout na nějaký block (kromě bedrocku), tak se rozbije, nás to nakrmí a nakonec se ještě přehraje zvuk snězení.
Particles
Jelikož bychom chtěli efekt solných particles na tom bloku co ničíme a teoreticky i proud particles od bloku k hráči, použijeme World metodu spawnParticle(String particleid,double x, double y, double z, double motionX, double motionY, int motionZ). Názvy particles i s obrázky zde . Zde budu chtít particle salt blocku, který jsem si vytvořil v min. díle. blockcrack_id_data
world.spawnParticle("blockcrack_"+Block.getIdFromBlock(BlocksManager.blockSul)+"_0", x, y+1, z, world.rand.nextGaussian(), world.rand.nextGaussian(), world.rand.nextGaussian());
Zde jenom připomínka, že používám Random atributu instance world.
Nyní, protože to vypadá cool, bych rád spawnul particles mezi hráčem a blockem, který ničí.
int posX=(int) player.posX; int posY=(int) player.posY; int posZ=(int) player.posZ; for (int i = 0;i<40;i++){ int xp=(int) (x-posX<0?x+world.rand.nextInt(Math.abs(x-posX)==0?1:Math.abs(x-posX)):posX+world.rand.nextInt(Math.abs(x-posX)==0?1:Math.abs(x-posX))); int yp=(int) (y-posY<0?y+world.rand.nextInt(Math.abs(y-posY)==0?1:Math.abs(y-posY)):posY+world.rand.nextInt(Math.abs(y-posY)==0?1:Math.abs(y-posY))); int zp=(int) (z-posZ<0?z+world.rand.nextInt(Math.abs(z-posZ)==0?1:Math.abs(z-posZ)):posZ+world.rand.nextInt(Math.abs(z-posZ)==0?1:Math.abs(z-posZ))); world.spawnParticle("blockcrack_"+Block.getIdFromBlock(BlocksManager.blockSul)+"_0", xp, yp, zp, 0,0, 0); }

A tímto bychom měli magickou solnou hůlku, s kterou můžu sníst téměř jakýkoli block. Avšak zrada! Kde ji jenom vzít! Možná by bylo fajn si ji vycraftit.
Crafting Shaped Recipes
Pro vytvoření receptů využijeme eventu init v naší třídě Main a metody addRecipe()/addShapedRecipe() = tyto 2 metody jsou totožné.(Respektive addRecipe() volá addShapedRecipe()).
GameRegistry.addShapedRecipe(new ItemStack(Items.golden_chestplate, 1), "y y", "yyy", "yyy", 'y', new ItemStack(Items.gold_ingot));
Takto vypadá craftící recept pro golden chestplate. Zde platí že první param je výsledná věc, kterou vyrábíme a další:
- max 3 stringy o délce max 3 kde platí, že první string jsou první max 3 okínka v crafting table.
- char který jsme používali v našich řetezcích
- Itemstack, který se vztahuje k charu, který jsem napsali v 2. kroku.
- opakujeme kroky 2 a 3 abych takto vypsali všechny chary použité v řetezcích a jejich přiřazení k itemstackům.
Jelikož jsme si vědom nepřehledosti v tomto zmateném výkladu, uvedu ještě pár jiných příkladů:
Piston
GameRegistry.addShapedRecipe(new ItemStack(Blocks.piston, 1), "ddd", "kzk", "krk", 'd', new ItemStack(Blocks.planks), 'k', new ItemStack(Blocks.cobblestone), 'z', new ItemStack(Items.iron_ingot), 'r', new ItemStack(Items.redstone));
Torch
GameRegistry.addShapedRecipe(new ItemStack(Blocks.torch, 4), "u", "k", 'u', new ItemStack(Items.coal), 'k', new ItemStack(Items.stick));
U torche receptu normálně platí, že uhlí nemusí být přesně v levém horním rohu, jediná důležitá věc je, aby pod ním byl klacík.
Slab
GameRegistry.addShapedRecipe(new ItemStack(Blocks.stone_slab, 6), "yyy", 'y', new ItemStack(Blocks.cobblestone));
U slabu také platí ignorace přesného řádku, kam se má cobblestone dát.
Náš SůlBlock
GameRegistry.addShapedRecipe(new ItemStack(BlocksManager.blockSul, 1), "ss", "ss", 's', new ItemStack(ItemsManager.itemSul));
Naše Hůlka
GameRegistry.addShapedRecipe(new ItemStack(ItemsManager.itemWand, 1), "d", "s", "s", 's', new ItemStack(ItemsManager.itemSul), 'd', new ItemStack(Items.diamond));
Zde doporučuji si pár receptíků zkusit udělat, abyste přišli na přesně správné chování tohoto craftícího zápisu, druhá varianta je se kouknout na zdroják metody addShapedRecipe().

Crafting Shapeless Recipes
Pokud chceme udělat nějakou směs, třeba smíchat 4 prášky, tak je nám asi jedno, ve kterém z 9 okínek se bude nacházet, hlavně že tam jsou. A k tomu je o dost jednodušší metoda addShapelessRecipe(Itemstack output,Itemstack... suroviny).
GameRegistry.addShapelessRecipe(new ItemStack(Items.bronz, 4), new ItemStack(Items.cín), new ItemStack(Items.měď), new ItemStack(Items.měď), new ItemStack(Items.měď));
Zde jsme přidali recept na výrobu bronzu z jednoho cínu a tří mědí.
Tak a je hotovo. Zdroják třídy ItemWand a Main ke stáhnutí pod článkem.
V další lekci, Minecraft Modding - Teleport 1. část, si vysvětlíme NBT TagCompound, Block Metadata, WorldSavedData a vytvoříme si Teleport.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 37x (4.13 kB)
Aplikace je včetně zdrojových kódů v jazyce Java