Lekce 5 - Minecraft Modding - Teleport 1. část
V předchozí lekci, Minecraft Modding - Solná hůlka a crafting, jsme si ukázali, jak pracovat s eventy a taky pár metod Worldu.
Dnes a příště si ukážeme, jak vytvořit dosti jednoduchý teleport. Ukážeme si zde práci s NBT a metadaty. Teleport se bude skládat z dvou teleportBloků a teleportačního ovladače, pomocí kterého vyvoříme mezi dvěma bloky spojení. Hráč poté přijde na tele-blok, klikne na něj pravým tlačítkem a jednoduše bude teleportován na druhý blok. (to samé z 2. bloku na 1. blok).
Nutné objekty
MetaData
Metadata (integer) můžeme nastavit každému bloku. Je uchováván ve Worldu a nikoli v třídě Block. Metadata je nejjednoduší způsob uchovávání nějakého stavu, např: barvy vln, typy dřeva, páčka, redstone torche apod. Výhodou je rychlost a také malý objem dat. Představte si, že byste museli napsat 16 tříd pro každou barvu vlny: BlockWoolWhite, BlockWoolOrange... Nevýhodou je přesně to samé a to malý objem dat. Pokud chceme například uložit stav truhly kde je 16 políček pro itemy, itemů je v MC hodně a ještě jich může být od 1 do 64 v každém políčku. Asi vás napadne že používat metadata je zde zhola nemožné - pro každý možný stav truhly potřebujeme jiné meta. Pro nastavování metadat jsou ve Worldu metody getBlockMetadata(int x,int y,int z) a setBlockMetadataWithNotify(int x, int y, int z, int meta).
NBT
NBT je formát vytvořený Notchem, pro ukládání MC světů. Je to uzlově založený formát, používaný např: v player.dat nebo level.dat. NBT Tag Compound (=složenina tagů) je schopný uchovat v sobě další NBT a tím pádem má neomezenou velikost. NBT je výborný, pokud potřebujeme uchovat více dat, než jsou metadata. Používá se např v : Chest, (všechny bloky s inventory), Sign a Book, kde je používán k uložení itemů, stavu, textu v knížce. Velikost objektů s NBT se ale dramaticky zvyšuje, takže neepoužívejte NBT pro objekty, které se přírodně vyskytují ve velkých množstvích. Určitě se nejprve zamyslete, zdali by se nemohlo použít radši metadata. Tento formát, jak již bylo řečeno, slouží k ukládání všech dat nějakého objektu (Block,Item). Je vytvořen proto, aby nebylo nutné ukládat celý objekt, ale pouze jeho data: když unloadneme World, zavolá se metoda writeToNBT(NBTTagCompound), která nám dá NBTtag a my do něj uložíme nějaké naše tagy z našich proměnných. Objekt je snězen, ale data se uložila. Při načtení světa se zase zavolá metoda readFromNBT(NBTTagCompound), která nám dá NBTtag, abychom si z něj do našeho nově vytvořeného objektu načetli všechna data, která jsme měli v našem snězeném objektu.
WorldSavedData
Je třída, určená k uchovávání tagů pro daný svět. To znamená, že i při reloadu světa tam ty informace budou. Instance této třídy musí mít svůj vlastní klíč (String), podle kterého jsou potom načítány. Ke každému Worldu nemůžou patřit 2 WorldSavedData se stejným klíčem. Pro ukládání a načítání tagů používáme metody writeToNBT(NBTTagCompound tag) a readFromNBT(NBTTagCompound tag). Při write ukládáme do tagu String název a za něj danou instanční proměnou, při readu ukládáme do proměnné hodnotu, kterou jsme přečetli z tagu za pomoci názvu.
Teorie
Nejprve bych radši vysvětlil celou strukturu a logiku našeho teleport-modu. Bude existovat jistý item = ovladač, který bude "spojovat" jednotlivé teleport-blocky. Teleport-blocky pak budou číst spojení vytvořené ovladačem a pomocí tohoto spojení portnou hráče na 2. block. Tak tolik k úvodu, ale teď jak na to? Pojďme se zamyslet jak bude spojení vypadat a jak ho budeme ukládat.
Spojení
Spojení budou tři vlastosti:
- Souřadnice prvního blocku (int[])
- Souřadnice druhého blocku (int[])
- Unikátní ID spojení (integer)
Ukládat ho budeme jednoduše pomocí NBT. Otázka ovšem je, jakému objektu bude NBT patřit. Toto NBT musí být vždy přístupno jak blockům, které budou portovat, tak itemu=ovladači, který bude spojení vytvářet. Z tohoto důvodu tento objekt musí být někde jinde. Nabízí se zde možnost hráče, do kterého bychom to uložili, avšak při pomyšlení na multiplayer to asi nebude ta správná volba. Jediné logické řešení je World nebo spíše WorldSavedData. Díky tomu bude mod fungovat i na MP a nebude závislý na hráčích, blocích či itemech.
Ovladač
Když s ním klikneme poprvé na block, si bude muset uložit souřadnice toho objektu. Až když s ním klikneme na 2. block, bude muset vytvořit spojení z uložených souřadnic předešlého blocku a nových souřadnic blocku, na který právě klikáme. K tomuto budeme zase potřebovat NBT. Když klikneme na první block, souřadnice blocku se uloží do itemu (tedy do NBT), a při kliknutí na druhý block se obě souřadnice uloží.
BlockPort
Zbývá už jenom Tele-Block, který se bude starat o vlastní portování.
Při kliknutí na block nejprve přečte z našeho World_NBT souřadnice a na ty
hráče portne. Bystřejší z vás jistě napadlo, jak block zjistí, které
spojení uložené ve World_NBT je to správné, protože ve World_NBT je mnoho
spojení a jak najít to pravé? K tomu už vám možná napověděla definice
spojení a jeho 3. atribut: Unikátní ID spojení. Řekli jsme
si přece, že toto ID bude integer a jak již jsem říkal metadata je taky
integer, takže je to jasné: použijeme metadata.
Kódíme
MyWorldData
public class MyWorldData extends WorldSavedData { private static final String key = "MujUnikatniKlic"; private static final String nbtName="muj_nbt_tag"; public NBTTagCompound tag; public MyWorldData(String key){ super(key); tag=new NBTTagCompound(); } public static MyWorldData forWorld(World world) { // vrátí instanci MyWorldData náležící k danému worldu, popřípadě vratí novou instanci, pokud ve worldu zatím instance není MapStorage storage = world.perWorldStorage; MyWorldData result = (MyWorldData)storage.loadData(MyWorldData.class, key); if (result == null) { result = new MyWorldData(key); storage.setData(key, result); } return result; } @Override public void readFromNBT(NBTTagCompound nbt) { tag=nbt.getCompoundTag(nbtName);//přečte tag z nbt a uloží ho do instance } @Override public void writeToNBT(NBTTagCompound nbt) { nbt.setTag(nbtName, tag);//přečte tag z instance a zapíše ho do nbt }
Zde jsme si vytvořili potomka třídy WorldSavedData a přidali jsme mu atribut NBTTagCompound, který správně ukládáme a zapisujeme pomocí metod write a read. Používáme přitom klíč k získání právě tohoto nbt, který je deklarován ve finální proměnné nbtName. Dále zde stojí za zmínku statická metoda forWorld(), která vrátí instanci MyWorldData uloženou ve světě.
Ovladač
public class ItemPortRemote extends Item { public static final String PORADI="Poradi"; public static final String TELEMANAGE="Teleport Management"; public static final String L1="l1"; public static final String L2="l2"; public ItemPortRemote(){ this.maxStackSize=1; this.setUnlocalizedName("port_remote"); this.setTextureName("port_remote"); } }
V ovladači si kromě základních věcí deklarujeme pár finálních proměnných, které budeme používat pro přístup do našeho MyWorldData.tag. Dále budeme potřebovat tuto metodu, která bude ukládat všechny proměnné, které bude muset ovladač mít, do NBT patřícímu itemStacku.
public void writeToNBT(int x, int y,int z, boolean MamData, ItemStack itemstack){ itemstack.stackTagCompound.setInteger("x", x); itemstack.stackTagCompound.setInteger("y", y); itemstack.stackTagCompound.setInteger("z", z); itemstack.stackTagCompound.setBoolean("MamData", MamData); }
To je pro dnešní lekci vše.
V dalším díle, Minecraft Modding - Teleport 2. část, nás čeká objektové uspořádání tagů našich
spojení, zajištění portování naším blockem a celkové dodělání. Pokud máte nějakou připomínku
nebo potřebujete pomoc, určitě napište.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkamiStaženo 691x (1.59 kB)