3. díl - Minecraft Modding - Konvence a SidedBlockTextures

Java Minecraft Modding Minecraft Modding - Konvence a SidedBlockTextures

V minulém díle jsme si přidali náš první item, ale my chceme více. Nyní bych rád začal pracovat s bloky, ale ještě předtím je nutné udělat si nějaký pořádek ve třídění itemů a bloků. Omlouvám se, že to nebude nic zábavného, ale v dalších dílech se nám to bude velice hodit.

Konvence v blocích a itemech a jejich utřídění

V minulém díle jsme tvořili custom item a používali jednoduchý public konstruktor třídy Item, kde jsme byli schopni nastavit nějaké základní atributy (např. textureName, UnlocalizedName) pomocí řetězení, ale! například jsme vůbec nebyli schopni reagovat na nějaké item eventy (např. kliknutí s itemem na něco, pravé tlačítko atd....). Pokud toto chceme upravovat, musíme si udělat potomka třídy Item, u kterého můžeme zbývající prázdné metody "doimplementovat". To samé platí s Blockem, avšak zde není na výběr, jelikož konstruktor Block(Material) je protected (skrytý) a tudíž musíme vytvořit potomka třídy Block, u kterého můžeme rovnou do jeho public konstruktoru doplnit atributy jako třeba blockName, Material, atd..) a proto je zde řetězení naprosto zbytečné. Nyní už k samotné konvenci. Tyto třídy (potomci) se musí samozřejmě někam uložit a to se provádí následujícím způsobem. Do stejného balíčku, ve kterém je balíček main, dáme nové balíčky, které pojmenujeme items a blocks. Do těchto balíčků budeme ukládat naše potomky tříd Block a Item. Při pojmenovávání potomků budeme dodržovat nejprve napsání svého předka (v našem případě Block nebo Item) a poté jeho vlastní jméno.

Př: ItemKrumpáč, BlockTalíř, BlockPlast, ItemHodinky, ItemNozik.

Třídy BlocksManager a ItemManager

Možná vás napadlo v minulém díle, že prakticky pro každý Item musíme vyhradit 2 řádky v Main třídě, což jest velice nepřehledné a při desítkách itemů a bloků naprosto zničující. Z toho důvodu je lepší, vytvořit třídy, které budou spravovat všechny itemy a bloky a na které já budu ze své Main třídy volat pouze jejich metody a ony se postarají o zbytek. Tím pádem budu mít v Main víc místa na konfiguraci modu, komunikaci s ost. mody atd.. Třídy se budou nacházet ve stejných balíčcích, jako jsou všichni potomci Block/Item. Budou vypadat takto:

package com.cooble.saltmod.blocks;

public class BlocksManager {

        public static void init(){}

        public static void register(){}

}

A to samé i u třídy ItemsManager. A takto budou vypadat při naplnění Itemy/Blocky:

public class ItemsManager {
        public static Item itemSul;
        public static Item itemNeznamy;

        public static void init(){
                itemSul = new Item().setUnlocalizedName("sul").setTextureName("sul");
                itemNeznamy = new ItemNeznamy();
        }

        public static void register(){
        GameRegistry.registerItem(itemSul,"itemSul");
        GameRegistry.registerItem(itemNeznamy,"itemNeznamy");
        }

}

A z naší třídy Main budeme pouze volat metody init() a register():

@Mod(modid = Main.MODID, version = Main.VERSION)
public class Main
{
    public static final String MODID = "SulMod";
    public static final String VERSION = "1.0";


    @EventHandler
    public void preInit(FMLPreInitializationEvent event){
        BlocksManager.init();
        BlocksManager.register();
        ItemsManager.init();
        ItemsManager.register();

    }

Zde je graf vztahů:

A zde složka finální (tak to bude vypadat na koci tohoto dílu) projektu:

Block

Block je podobná třída jako Item, avšak u ní nemůžeme použít její konstruktor, protože je skrytý. A jediná možnost, jak získat instanci je vytvoření potomka této třídy, který by mateřský konstrukor doplnil. A proto pokud budeme chtít vytvořit blok musíme vždy vytvořit třídu, která dědí z Block, a tudíž se může za Block vydávat. Vytvoříme si tedy novou třídu (dodržujme konvenci: BlockNázevbloku)

package com.cooble.saltmod.blocks;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;

public class BlockSul extends Block {

        protected BlockSul() {
                super(Material.rock);
                this.setCreativeTab(CreativeTabs.tabBlock);
                this.setBlockName("blockSul");
                this.textureName="block_sul";
        }
}

Nyní již stačí do BlocksManageru tento block přidat:

public class BlocksManager {
        public static Block blockSul;

        public static void init(){
                blockSul = new BlockSul();
        }

        public static void register(){
                GameRegistry.registerBlock(blockSul, "blockSul");
        }
}

Jak jsem již říkal, je zbytečné psát do BlockManageru:

blockSul = new BlockSul().setBlockName("blockSul").setNeco().atd();

protože vše se strčí už do konstruktoru BlockSul().

Textury

Samozřejmě ještě musíme strčit do naší složky /src/assets/mi­necraft/textu­res/blocks obrázek "block_sul.png". (ke stáhnutí pod článkem). No a máme hotovo, block by již měl fungovat i s texturou.

SidedTextury

Jistě jste si všimli, že na všech šesti stranách je ta samá textura, což nám v nějakých případech může vadit a chtěli bychom třeba nahoře stříšku, dole dno, po stranách okínka. Založme si tedy novou třídu BlockSloup (stačí pouze zkopírovat BlockSul a přejmenovat) a nezampomeňme na registraci BlockSloupu v BlocksManageru.

Nejprve definujeme atribut BlockSloupu a to pole Iconek(obrázků)

private IIcon[] textury = new IIcon[6];

6 protože každý block má 6 stran (pochopitelně můžeme udělat jenom 2 velké nebo 3,4,5, záleží na počtu obrázků u blocku). Poté musíme do našeho pole uložit IIcony, to uděláme pomocí metody registerIcon(String názevSouboru/o­brázku např: "block_sloup_ 0"):

@Override
    public void registerBlockIcons(IIconRegister register){
        for (int i = 0; i < textury.length; i++) {
                        textury[i]=register.registerIcon(this.textureName+"_"+i);
                }
    }

Tímto způsobem jsme získali všechny IIcony, které budeme potřebovat. Nyní je zbývá jen předat Minecraftu, který je vykreslí. Na to je tato metoda.

@Override
        public IIcon getIcon(int side, int meta) {
                return textury[side];
        }

Tato metoda má za parametry stranu bloku(0|1|2|3|4|5) (0=spodní, 1=horní.. viz. obrázek) a jako druhý metadata bloku (tím se prozatím nehodlám zaobírat). Čili Minecraft se nás zeptá na IIconku, kterou má vykreslit stranu bloku, kterou nám předá jako parametr side. Zde se nemusíme bát IndexOutOfBou­ndsException jelikož jsme vytvořili pole s délkou 6 a side bude vždy pouze od 0 do 5.

Samozřejmě že nemusíte dělat pole klidně si stačí udělat třeba 2 IIconky, ale myslím si že pole je nejlepší. Takže nyní máme hotovo a po spuštění Minecraftu bychom měli najít náš speciál BlockSloup, zde ho předkládám s mírnou úpravou.

.

package com.cooble.saltmod.blocks;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.util.IIcon;

public class BlockSloup extends Block {

        private IIcon[] textury = new IIcon[2];

        protected BlockSloup() {
                super(Material.rock);
                this.setCreativeTab(CreativeTabs.tabBlock);
                this.setBlockName("blockSloup");
                this.textureName="block_sloup";
        }

        @Override
        public IIcon getIcon(int side, int meta) {
                if(side==1) //pokud top
                        return textury[1];
                else
                        return textury[0];
        }
        @Override
        public void registerBlockIcons(IIconRegister register) {
                textury[0]=register.registerIcon(textureName+"_"+0);
                textury[1]=register.registerIcon(textureName+"_"+1);

        }

}

Nakonec je zde finální podoba blockSloupu, ze všech stran až na horní je normální textura soli, avšak na topu (nahoře) je textura s černým puntíkem.

Jak fungují IIconky

Interface IIcon se používá v Minecraftu k dostání textury bloku/itemu na specifické straně. Jediné 2 třídy implementující tento interface jsou TextureAtlasSpri­te a IconFlipped. IIcon neuchovává aktuální texturu, nýbrž místo na texture mapě, která je Minecraftem vytvořena vždy při startu hry, či změnění texturepacku. Tato texture mapa je vytvořena třídou TextureMap implementující rozhraní IIconRegister. Texture mapa je vytvořena hned po eventu preInit. Při tomto tvoření Zavolá TextureMap na všechny bloky/itemy metodu registerIcons(I­IconRegister), která je registruje a vybere pro ně místo na texture mapě, kam je uloží a vrátí odkaz na místo na té texture mapě=IIcon. (V dávných verzích Minecraftu jsme tvořili rovnou texture mapy, nyní je to přehlednější.) Velikost texture mapy závisí na počtu a velikosti textur. Normálně má block texture mapa rozměry 256*256. Pokud přidáme třeba jen jedinou texturu 32*32 TextureMap zvětší texture mapu na 512*512. Blok i item mají přirozeně také IIcon a to v protected atributu blockIcon/ite­mIcon.

Závěr

Tím bych tento díl ukončil, naučili jsme se správnému zápisu a třídění itemů a bloků ve třídách a přidali jsme si 2 bloky: BlockSul a BlockSloup, který na rozdíl od BlockSoli má na horní staně černou tečku. Tím jsme se naučili i nastavování textur bloku z každé strany jinak. Nakonec jsme si vysvětlili IIconky. Pokud máte nějaké problémy či dotazy, určitě napište.


 

Stáhnout

Staženo 16x (2.61 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

  Aktivity (1)

Článek pro vás napsal Matěj Černý
Avatar
Autor se věnuje programování v Javě, moduje Java hru Minecraft a pracuje se Cinema4D.

Jak se ti líbí článek?
Celkem (8 hlasů) :
4.254.254.254.25 4.25


 


Miniatura
Všechny články v sekci
Minecraft Modding

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!