Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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_da­ta

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);
}
Minecraft Modding

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()/ad­dShapedRecipe() = 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ší:

  1. max 3 stringy o délce max 3 kde platí, že první string jsou první max 3 okínka v crafting table.
  2. char který jsme používali v našich řetezcích
  3. Itemstack, který se vztahuje k charu, který jsem napsali v 2. kroku.
  4. 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().

Po vložení textury a přejmenování - Minecraft Modding

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 addShapelessRe­cipe(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 35x (4.13 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Minecraft Modding - Konvence a SidedBlockTextures
Všechny články v sekci
Minecraft Modding
Přeskočit článek
(nedoporučujeme)
Minecraft Modding - Teleport 1. část
Článek pro vás napsal Matěj Černý
Avatar
Uživatelské hodnocení:
11 hlasů
Autor se věnuje programování v Javě, C++, zajímá se o OpenGL.
Aktivity