Zaloguj lub zarejestruj się aby zobaczyć ten link. (W tym poście, poniżej) 2. Zaloguj lub zarejestruj się aby zobaczyć ten link. 3. Zaloguj lub zarejestruj się aby zobaczyć ten link. 4. Zaloguj lub zarejestruj się aby zobaczyć ten link. 5. Zaloguj lub zarejestruj się aby zobaczyć ten link. 6. Zaloguj lub zarejestruj się aby zobaczyć ten link. 7. Zaloguj lub zarejestruj się aby zobaczyć ten link. 8. 513fac..."> Zaloguj lub zarejestruj się aby zobaczyć ten link. (W tym poście, poniżej) 2. Zaloguj lub zarejestruj się aby zobaczyć ten link. 3. Zaloguj lub zarejestruj się aby zobaczyć ten link. 4. Zaloguj lub zarejestruj się aby zobaczyć ten link. 5. Zaloguj lub zarejestruj się aby zobaczyć ten link. 6. Zaloguj lub zarejestruj się aby zobaczyć ten link. 7. Zaloguj lub zarejestruj się aby zobaczyć ten link. 8. 513fac..."> Skocz do zawartości
Minecraft.pl Server Banner
Mevistor

[TUTORIAL] Kurs pisania modów (Minecraft Forge)

Rekomendowane odpowiedzi

Mevistor    31

SPIS TREŚCI

 

1.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

(W tym poście, poniżej)

2.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

3.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

4.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

5.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

6.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

7.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

8.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

9.

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

 

 

Gotowy mod do wgrania na wasz serwer lub na singla "Tutorial cz.9" (katalog "%appdata%/.minecraft/mods"): 

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

Kod źródłowy "Tutorial cz.9": 

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

 

Witam!  :crazy: 

 

Chciałbym stworzyć tutorial całkowicie w języku polskim o tworzeniu modów pod Forge'a. Wiele osób nie wie, że pisanie modów do Minecraft'a może być bardzo proste. Chciałbym właśnie to wam pokazać.

Postaram się napisać tutorial w kilku częściach. W każdej dodam coś nowego. Stworzymy w ten sposób jeden duży mod do Minecraft'a.

 

Komentujcie co o tym sądzicie, czy warto tworzyć takie coś. Chciałbym też wiedzieć co na to Administratorzy strony.

Jeśli wam się spodobało to jutro postaram się umieścić część 2, w której dodamy do gry 16 nowych rodzajów bloków, a dokładniej szesnaście nowych rodzajów kwiatów!

 

 

 

Potrzebne nam będzie:

- Forge

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 (pobieramy plik src)

- Eclipse

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

Modyfikacja powstaje na wersji: Minecraft 1.6.2

 

Nie będę omawiał sposobu instalacji Forge'a ani obsługi Eclipse. Nie jest to zbyt skomplikowane. Dla "niewiedzących" na google są poradniki :crazy:

 

TUTORIAL cz.1 - Podstawowe pliki modyfikacji!

 

1. Tworzymy plik główny modyfikacji.

 

W Eclipse klikamy po lewej stronie na "src" prawym przyciskiem myszki i wybieramy: "New --> Package".

Następnie podajemy nazwę naszej "paczki". W moim przypadku nazwę ją "modmevipack" (nawa musi być pisana małymi literami). Najczęściej wpisujemy tutaj nazwę naszego moda, czyli tak jak się będzie nazywał w przyszłości. 

 

1XBr7C.jpg

 

Następnie klikamy prawym przyciskiem myszy na naszą paczkę i wybieramy "New --> Class". W niej napiszemy podstawę naszego moda. Nasz plik Class nazywamy "ModMeviPack" (nazwa dowolna, ja nazwałem ją tak samo jak mój Mod).

 

Otwarł nam się pusty dokument, więc przechodzimy do pisania.  :crazy:

 

Na początku stworzymy podstawę naszego pliku.

Piszemy:

@Mod(modid = "modmevipack", name = "ModMeviPack", version = "1.2.0")
@NetworkMod(clientSideRequired = true, serverSideRequired = false)

public class ModMeviPack 
{

}

@Mod

- "modid" - jest to unikalny identyfikator naszego moda

- "name" - nazwa naszego moda

- "version" - wersja naszego moda

 

@NetworkMod

Podajemy tutaj po której stronie (Client albo Serwer, lub oba) nasz mod będzie wymagany. Najczęściej pozostawiamy jak powyżej napisałem.

 

Teraz w klasie głównej ModMeviPack piszemy:

@Instance("ModMeviPack")
public static ModMeviPack instance;
	
@SidedProxy(clientSide="modmevipack.ClientProxy", serverSide="modmevipack.CommonProxy")
public static CommonProxy proxy;
		
@EventHandler
public void preInit(FMLPreInitializationEvent event) 
{	

}
	
@EventHandler
public void Load(FMLInitializationEvent event) 
{

}
	
@EventHandler
public void postInit(FMLPostInitializationEvent event)
{
		
}

Tutaj interesuje nas najbardziej kod: "@SidedProxy(clientSide="modmevipack.ClientProxy", serverSide="modmevipack.CommonProxy")". Musimy stworzyć dwie kolejne klasy. Są to pliki uruchamiane albo po stronie Klienta albo Serwera. Narazie nie będziemy na tym etapie programowania zajmować się tymi plikami, więc polecam ten kawałek kodu pozostawić bez zmian, a pliki do nich stworzyć już "na zapas".

 

Tworzymy więc kolejne dwie nowe klasy. Klikamy prawym przyciskiem myszy na paczkę "modmevipack" i dajemy: "New --> Class". Pierwszy z plików nazywamy "ClientProxy", a drugi "CommonProxy".

 

Ich zawartość:

 

ClientProxy

package modmevipack;

public class ClientProxy extends CommonProxy
{
	@Override
        public void registerRenderers() 
	{	
		
	}
}

CommonProxy

package modmevipack;

public class CommonProxy 
{
	public void registerRenderers() 
	{	
		
        }
}

Nasza struktura plików powinna więc wyglądać teraz tak:

 

2NEUlv.jpg

 

Stworzyliśmy podstawową część naszego moda!

 

W następniej części dodamy:

- Nową zakładkę do Trybu Creative

- 16 nowych rodzajów kwiatów

 

Cały kod głównego pliku modyfikacji wygląda więc tak:

 

ModMeviPack

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack;

import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;

@Mod(modid = "modmevipack", name = "ModMeviPack", version = "1.2.0")
@NetworkMod(clientSideRequired = true, serverSideRequired = false)

public class ModMeviPack 
{
	@Instance("ModMeviPack")
        public static ModMeviPack instance;
	
	@SidedProxy(clientSide="modmevipack.ClientProxy", serverSide="modmevipack.CommonProxy")
        public static CommonProxy proxy;
	
	
	@EventHandler
        public void preInit(FMLPreInitializationEvent event) 
	{	

	}
	
	@EventHandler
        public void Load(FMLInitializationEvent event) 
	{

	}
	
	@EventHandler
        public void postInit(FMLPostInitializationEvent event)
	{
		
	}
}

PS: Przepraszam za moje błędy w ortografi  :confused:

 

Całość kodu do pobrania tutaj: 

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

 (jeśli znacie lepszy hosting to proszę o polecenie mi)

 

I gratulacje, +1 za usuwanie dopisków moderatorskich. //Chormon

Edytowane przez Mevistor

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!  :crazy: 

Miałem dzisiaj napisać tutorial o nowych blokach (kwiatach) ale z przyczyn prywatnych (musiałem zostać dłużej w pracy) nie mam już dzisiaj sił i czasu żeby stworzyć tak obszerny poradnik. Postanowiłem napisać dzisiaj o tworzeniu Zakładek (Creative Tabs) w trybie Creative. Stworzymy więc zakładkę która będzie nam bardzo ułatwiać życie. Będziemy wrzucać do niej wszystki Bloki i Item'ki które napiszemy w przyszłości.

 

Jutro dodam tutorial o tworzeniu nowych Bloków (Kwiatów). Jeszcze raz przepraszam.  :((

 

Cały dzisiejszy efekt będzie się prezentował tak:

 

1SDrG.jpg

 

TUTORIAL cz.2 - Tworzymy nowy Creative Tab! 

 

1. Tworzymy Creative Tab

 

Crative Tab to nic innego jak nowa zakładka w trybie Creative. Ułatwia to segregowanie przedmiotów. My stworzymy swoją i do niej będziemy wrzucać wszystkie napisane przez nas bloki i item'ki.

 

Tworzymy nowy plik class. Klikamy na naszą paczkę ModMeviPack i wybieramy: New --> Class. Nowy plik nazwiemy sobie np: CreativeTabsMP.

 

Zaczynamy pisać. 

 

CreativeTabsMP.java

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack;

import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;

public class CreativeTabsMP extends CreativeTabs
{
	public CreativeTabsMP(String par1) 
	{
		super(par1);
		
	}
	
	public ItemStack getIconItemStack() 
	{
		return new ItemStack(Block.cactus);
	}
}

Opiszmy kod:

public class CreativeTabsMP extends CreativeTabs 

Jak zauważyliście do nazwy klasy dodaliśmy dopisek: "extends CreativeTabs". Jest to znak dla gry, że ten plik będzie zakładką w trybie Creative. W następnych tutorial'ach dowiecie się, iż możemy dopisać tam np: Block, Item lub ItemFood. Jeśli znacie angielski to zorientujecie się co to oznacza.

public CreativeTabsMP(String par1) 
	{
		super(par1);
		
	}

Jest to tak zwany kreator naszej klasy (Class). W większości plików które będziemy tworzyć musi się on znaleźć. Zauważyliście, że ta procedura posiada przedrostek public. Public oznacza, iż ta procedura jest publiczna i widoczna również poza tym plikiem.

public ItemStack getIconItemStack() 
	{
		return new ItemStack(Block.cactus);
	}

Ta procedura dodaje ikonkę do naszej zakładki. Ja wybrałem ikonę kaktusa. Jeśli wykasujecie zawartość nawiasów (Block.cactus) i wpiszecie samo Block z kropeczką to Eclipse wyświetli wam listę bloków o Item'ków dostępnych w Minecrafcie. W ten sposób możecie zmienić ikone naszej zakładki. Pokazałem to poniżej. Wybierzcie inny na próbę a zobaczycie  :crazy:

 

2WhZ1.jpg

 

Przejdźmy dalej. Otwórzmy plik główny ModMeviPack.java i dopiszmy parę rzeczy. Po dopisaniu będzie on wyglądał tak:

 

ModMeviPack.java

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack;

import modmevipack.language.LanguageMP;
import modmevipack.mods.ModFlowersMP;
import net.minecraft.creativetab.CreativeTabs;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.registry.LanguageRegistry;

@Mod(modid = "modmevipack", name = "ModMeviPack", version = "1.2.0")
@NetworkMod(clientSideRequired = true, serverSideRequired = false)

public class ModMeviPack 
{
	@Instance("ModMeviPack")
        public static ModMeviPack instance;
	
	@SidedProxy(clientSide="modmevipack.ClientProxy", serverSide="modmevipack.CommonProxy")
        public static CommonProxy proxy;
	
	public static CreativeTabs mTabModMeviPack = (new CreativeTabsMP("ModMeviPack0"));
	
	@EventHandler
        public void preInit(FMLPreInitializationEvent event) 
	{	

	}
	
	@EventHandler
        public void Load(FMLInitializationEvent event) 
	{
             LanguageRegistry.instance().addStringLocalization("itemGroup.ModMeviPack0", "Mod MeviPack 1.2.0");
        }

        @EventHandler
        public void postInit(FMLPostInitializationEvent event)
	{
		
	}
}

A więc:

public static CreativeTabs mTabModMeviPack = (new CreativeTabsMP("ModMeviPack0"));

Tworzy zmienną mTabModMeviPack (tak ją sobie nazwałem, wy możecie jak chcecie) i przypisuje jej plik który przed chwilą stworzyliśmy (tak w łatwy sposób mogę to wytłumaczyć). W nawiasie na końcu podajemy nazwę naszej zakładki, może być ona dowolna.

LanguageRegistry.instance().addStringLocalization("itemGroup.ModMeviPack0", "Mod MeviPack 1.2.0");

Ta część kodu przypisuje nazwę naszej zakładki. Nazwa ta będzie wyświetlana gdy najedziemy myszką na naszą zakładkę.

 

Naciskamy na przycisk Run. Gra się uruchomi. Idziemy w tryb Creative. Jeśli wszystko zrobiliście tak jak pisałem zobaczycie, że macie nową, waszą zakładkę  :crazy:

 

Nie będę dzisiaj wrzucał całości kodu na SourceForge'a do pobrania, gdyż jutro napisze kolejny poradnik do kwiatach i wtedy umieszczę całość  :crazy:

Komentujcie i oceniajcie !

 

Tyle na dzisiaj.

Pozdrawiam Mevistor!

Edytowane przez Mevistor

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!  :crazy:

 

No to dzisiaj zajmiemy się pisaniem naszych bloków - kwiatów. Co tu dużo mówić.... Zaczynamy...

 

4UFuoK.jpg

 

5qGi6P.jpg

 

TUTORIAL cz.3 - Nowe bloki - kwiaty!

 

1. Główny plik bloku kwiatów.

 

Stworzymy teraz główny plik class naszego bloku. Jednak najpierw stwórzmy nową paczkę tak żeby było nam się w przyszłości łatwiej połapać w tym wszystkim. Tworzymy nową paczkę. W tym celu klikamy na główną naszą paczkę prawym przyciskiem myszy i wybieramy: New --> Package. Następnie w polu nazwy dopisujemy: ".blocks", tak aby cała nazwa brzmiała: "modmevipack.blocks". Tworzymy w ten sposób coś w stylu podfolderu w folderze "modmevipack".

1qGHR.jpg

 

Następnie klikamy na stworzoną wcześniej paczkę prawym przyciskiem myszy i tworzymy nowy plik Class. Nazywamy go "BlockFlowersMP". Nazwę możecie dać dowolną, ale ważne jest to żebyście się później orientowali co w jakim pliku mamy.

 

Zawartość pliku powinna wyglądać tak:

 

BlockFlowersMP.java

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.blocks;

import java.util.List;

import modmevipack.ModMeviPack;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.Icon;
import net.minecraft.world.World;
import net.minecraftforge.common.EnumPlantType;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.common.IPlantable;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class BlockFlowersMP  extends Block implements IPlantable
{
	private static final String[] nameflowers = new String[] {"00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15"};   
	@SideOnly(Side.CLIENT)
	private Icon[] textures; 
	
	public BlockFlowersMP(int par1) 
	{
		super(par1, Material.plants);
		this.setTickRandomly(true);
                float f = 0.2F;
                this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 3.0F, 0.5F + f); 
                this.setStepSound(Block.soundGrassFootstep); 
                this.setCreativeTab(ModMeviPack.mTabModMeviPack);
	}
	
	public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
        {
                return this.canBlockStay(par1World, par2, par3, par4);
        }
	
	protected boolean canThisPlantGrowOnThisBlockID(int par1)
        {
                return par1 == Block.grass.blockID || par1 == Block.dirt.blockID || par1 == Block.tilledField.blockID;
        }
	
	public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
        {
                this.checkFlowerChange(par1World, par2, par3, par4);
        }
	
	protected final void checkFlowerChange(World par1World, int par2, int par3, int par4)
        {
             if (!this.canBlockStay(par1World, par2, par3, par4))
             {
                    this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
                    par1World.setBlock(par2, par3, par4, 0, 0, 2);
             }
        }
	
	public boolean canBlockStay(World par1World, int par2, int par3, int par4)
        {
               Block soil = blocksList[par1World.getBlockId(par2, par3 - 1, par4)];
        
               return (par1World.getFullBlockLightValue(par2, par3, par4) >= 8 || par1World.canBlockSeeTheSky(par2, par3, par4)) && 
               (soil != null && soil.canSustainPlant(par1World, par2, par3 - 1, par4, ForgeDirection.UP, this));
        }
	
	public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
        {
              return null;
        }
	
	public boolean isOpaqueCube()
        {
              return false;
        }
	
	public boolean renderAsNormalBlock()
        {
              return false;
        }
	
	public int getRenderType()
        {
             return 1;
        }
	
	@Override
	public int damageDropped(int meta)
	{
		return meta;
	}

	@Override
	public int getDamageValue(World world, int x, int y, int z)
	{
		return world.getBlockMetadata(x, y, z);
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public Icon getIcon(int side, int meta)
	{
		if (meta < 0 || meta >= this.textures.length) 
		{
			meta = 0;
		}
		
		return this.textures[meta];
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void getSubBlocks(int blockID, CreativeTabs creativeTabs, List list) 
	{
		for (int i = 0; i < this.nameflowers.length; ++i) 
		{
			list.add(new ItemStack(blockID, 1, i));
		}
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void registerIcons(IconRegister iconRegister)
	{
		this.textures = new Icon[this.nameflowers.length];

		for (int i = 0; i < this.nameflowers.length; ++i) 
		{
			this.textures[i] = iconRegister.registerIcon("modmevipack:flowers/mFlower" + this.nameflowers[i]);
		}
	}
	
	@Override
	public EnumPlantType getPlantType(World world, int x, int y, int z) 
	{
		return EnumPlantType.Plains;
	}

	@Override
	public int getPlantID(World world, int x, int y, int z) 
	{
		return this.blockID;
	}

	@Override
	public int getPlantMetadata(World world, int x, int y, int z) 
	{
		return world.getBlockMetadata(x, y, z);
	}
}

A więc wytłumaczmy co za co odpowiada:

 

Na samym początku widzimy, że tworzymy dwie zmienne "nameflowers" oraz "textures". Odpowiadają one za przetrzymywanie danych wyglądu naszych kwiatów. Pierwsza to nazwy naszych kwiatów w plikach .png, a druga przechowuje te pliki jako tekstury w grze.

public BlockFlowersMP(int par1) 

I tutaj znów widzimy kreator naszej klasy. O kreatorach pisałem w poprzedniej części tutorialu.

float f = 0.2F;
this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 3.0F, 0.5F + f); 

Każdy normalny blok, np: ziemi, ma wymiary 1x1x1. W tej części kodu zmniejszamy go troszeczkę. Nasz blok dzięki temu będzie miał wielkość standardowego kwiatka w grze.

this.setStepSound(Block.soundGrassFootstep);

Tutaj chyba się domyślacie, że chodzi o dźwięk, Tak, ta część kodu odpowiada za dodanie odgłosu specyficznego dla tego bloku. Popróbujcie z innymi wartościami, np: zamiast "soundGrassFootstep" wybierzcie "soundStoneFootstep".

this.setCreativeTab(ModMeviPack.mTabModMeviPack);

Tutaj jest wszystko oczywiste. Nasz blok dodamy do zakładki którą stworzyliśmy w poprzedniej części.

 

Teraz opisze poszczególne funkcje:

public boolean canPlaceBlock(World par1World, int par2, int par3, int par4)

Funkcja ta sprawdza czy w danym miejscu możemy postawić nasz kwiatek. Jeśli np: klikniemy na bloku ziemi naszym kwiatkiem i spełni on wymagania do posadzenia go, to nasz kwiatek zostanie postawiony w tym miejscu. 

protected boolean canThisPlantGrowOnThisBlockID(int par1)

Funcja ta informuje grę na jakich blokach może rosnąć nasz kwiatek. W tym wypadku jest to: blok ziemi, blok ziemi z trawą oraz pole uprawne.

public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
protected final void checkFlowerChange(World par1World, int par2, int par3, int par4)

Jeśli zniszczymy któryś z sąsiednich bloków naszego kwiatka funkcja ta zostanie wywołana, np: jeśli przekopiemy blok pod naszym kwiatkiem, funkcja sprawdzi czy może on w tym miejscu dalej rosnąć. Jeśli okaże się że nie, a tak będzie, usunie go.

 

Pozostałe funkcje odpowiadają głównie za wygląd naszego bloku, czy blok jest cały "kwadratowy" - w naszym przypadku nie.

No i oczywiście za rodzaj kwiatka. Stworzyliśmy jeden blok, ale będzie on mógł przyjąć jeden z szesnastu wyglądów.

Nasz blok zawiera taką zmienną, która nazywa się "meta" i zawiera w sobie numerek od 0 do 15. My każdemu z tych numerków przypisujemy inny wygląd kwiatka.

Dla przykładu: jeśli nasz blok będzie zawierał w "meta" cyferkę "1" to nasz kwiatek będzie wyglądał jak róża, a jak "2" to jak tulipan.

To właśnie jest opisane w pozostałych funkcjach.

 

Przykładem w grze takiego rozwiązania jest np: blok desek. Jeśli meta w tym bloku ma "1" to wygląda jak deski dębowe, a jeśli "2" to wyglądają jak świerkowe.

 

2. Tworzymy nową klase ItemBlock.

W związku z tym że tworzymy tylko jeden blok, ale będzie on przyjmował aż 16 różnych kształtów, musimy stworzyć kolejną klase która nam te kształty będzie zmieniała.

Tworzymy nową paczkę. Oczywiście klikamy na naszej głównej paczce i tworzymy nową, którą nazwiemy "modmevipack.itemblocks".

W utworzonej przed chwilą paczce tworzymy nową klasę i nazywamy ją: "ItemBlockFlowersMP".

 

Zawartość pliku:

 

ItemBlockFlowersMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.itemblocks;

import net.minecraft.block.Block;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class ItemBlockFlowersMP extends ItemBlock
{
	public ItemBlockFlowersMP(int par1) 
	{
		super(par1);
		this.setHasSubtypes(true);
	}
	
	@Override
	public String getUnlocalizedName(ItemStack par1)
        {
		String name = "";
        switch(par1.getItemDamage())
        {
               case 0: 
               		{
            			name = "mFlower00";
            			break;
               		}
               case 1: 
               		{
               			name = "mFlower01";
               			break;
               		}
               case 2: 
               		{
               			name = "mFlower02";
               			break;
               		}
               case 3:
            	   	{
            	   		name = "mFlower03";
            	   		break;
            	   	}
               case 4: 
            	  	{
            		        name = "mFlower04";
            		        break;
            	  	}
               case 5: 
            	   	{
            	   		name = "mFlower05";
            	   		break;
            	   	}
               case 6: 
            	   	{
            	   		name = "mFlower06";
            	   		break;
            	   	}
               case 7: 
            	   	{
            	   		name = "mFlower07";
            	   		break;
            	   	}
               case 8: 
            	   	{
            	   		name = "mFlower08";
            	   		break;
            	   	}
               case 9: 
            	   	{
            	   		name = "mFlower09";
            	   		break;
            	   	}
               case 10: 
            	   	{
            	   		name = "mFlower10";
            	   		break;
            	   	}
               case 11: 
            	   	{
            	   		name = "mFlower11";
            	   		break;
            	   	}
               case 12: 
            	   	{
            	   		name = "mFlower12";
            	   		break;
            	   	}
               case 13: 
            	   	{
            	   		name = "mFlower13";
            	   		break;
            	   	}
               case 14: 
            	   	{
            	   		name = "mFlower14";
            	   		break;
            	   	}
               case 15: 
            	   	{
            	   		name = "mFlower15";
            	   		break;
            	   	}
               
               default: name = "mFlower00";
        }
               return "modmevipack:flowers/" + name;
        }
	
	@Override
	@SideOnly(Side.CLIENT)
	public boolean isFull3D()
	{
		return true;
	}
	
	@Override
	public int getMetadata(int par1)
        {
          return par1;
        }
    
        @Override
	public Icon getIconFromDamage(int meta)
	{
		return Block.blocksList[this.itemID].getIcon(0, meta);
	}
}

Klasa ta pobiera z naszego bloku wartość "meta". Poprzez funkcje "switch" sprawdza jej wartość i na jej podstawie nadaje naszemu blokowi wygląd gatunku kwiatka. To tak w skrócie.  :crazy:

 

3. Estetyka ułatwia życie!

W celach estetyczny kodu, zawsze pisząc moda, rozdzielam sobie kod tak aby w jednym pliku nie robić bałaganu. Są to tylko i wyłącznie cele kosmetyczne ułatwiające mi poruszanie się w kodzie.

W tym celu tworzymy kolejną nową paczkę klikając na naszej głównej paczce (dziwnie mi te stwierdzenie wyszło - mam nadzieje że wiecie o co chodzi  :crazy: ). Nazywamy ją: "modmevipack.mods", a w niej nową klase: "ModFlowersMP".

 

Całość struktury powinna wyglądać teraz tak:

2nfFi6.jpg

 

Zawartość pliku:

 

ModFlowersMP.java

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.mods;

import modmevipack.blocks.BlockFlowersMP;
import modmevipack.itemblocks.ItemBlockFlowersMP;
import net.minecraft.block.Block;
import net.minecraftforge.common.MinecraftForge;
import cpw.mods.fml.common.registry.GameRegistry;

public class ModFlowersMP 
{
	public static final Block mFlowers = (new BlockFlowersMP(3000));
	
	public static void init_Flowers()
	{
		for (int i = 0; i < 16; i++ )
			MinecraftForge.addGrassPlant(mFlowers, i, 15);
		
		GameRegistry.registerBlock(mFlowers, ItemBlockFlowersMP.class, (mFlowers.getUnlocalizedName().substring(5)));
	}
}

Co my tu mam? A więc:

public static final Block mFlowers = (new BlockFlowersMP(3000));

Tutaj przypisujemy do zmiennej nasz nowy blok o ID np: 3000.

public class ModFlowersMP 

Do tej funkcji odwołamy się za chwilę z głównego pliku naszego moda (to właśnie nazywam estetyką, gdyż zawartość tej funkcji mogli byśmy umieścić w głównym pliku).

MinecraftForge.addGrassPlant(mFlowers, i, 15);

Wykonuje się tu pętla która dodaje każdy z naszych kwiatów do.... hmmm.. jak by to nazwać. Powiem tak: Jeśli klikniemy mączką kostną na ziemi to zasieje nam się trawa, a czasem wyskoczy jakiś kwiatek. I właśnie tam w tą "opcje" wrzucamy nasze kwiatki. Teraz jak klikniemy mączką kostną na ziemi to czasem wyskoczą też nasze kwiatki  :crazy:

GameRegistry.registerBlock(mFlowers, ItemBlockFlowersMP.class, (mFlowers.getUnlocalizedName().substring(5)));

Ta część kodu jest niezbędna i bardzo ważna - rejestruje nasz blok w grze.

 

4. Małe zmiany w pliku głównym.

Przechodzimy do pliku głównego nasze modyfikacji, a więc do "ModMeviPack.java". 

W funkcji "load", między nawiasami dopisujemy:

ModFlowersMP.init_Flowers();

Funkcja ta powinna wyglądać teraz tak:

    @EventHandler
    public void Load(FMLInitializationEvent event) 
	{
		ModFlowersMP.init_Flowers();
	}

5. Koniec pisania na dzisiaj. Czas na grafike.

Skończyliśmy pisać dzisiaj nasz mod, no ale co nam po kwiatkach skoro nie mają grafiki.

 

W związku z tym że jestem słaby w rysowaniu, to grafikę do kwitów znalazłem na google lub w innych modach opartych na kodzie OpenSource. Wykorzystam ją tylko i wyłącznie w celu napisania tego poradnika.

 

Grafike do naszego moda należy umieścić w:

 

(Katalog Forge'a)\mcp\src\minecraft\

 

w tym katalogu tworzymy nowy folder o nazwie "assets" i w niem będziemy tworzyć całą strukturę grafiki do naszego moda.

 

Stórzcie w katalogu "assets" kolejny folder o nazwie naszego moda, czyli "modmevipack", a w nim kolejny folder "textures", i w nim kolejny "blocks", a w nim jeszcze jeden folder "flowers". I właśnie w nim będziemy umieszczać grafikć naszych kwiatów.

3h9owS.jpg

 

Grafika dla was do pobrania, oraz cały kod źródłowy z małą niespodzianką której dzisiaj nie opisałem, znajduje się w linku na dole.  :crazy:

 

To tyle na dzisiaj. Narazie.

 

Pozdrawiam, Mevistor!

 

 

 

Do pobrania kod + grafika: 

 

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Na dniach planowałem wypuścić kolejny tutorial, ale w związku z tym iż wychodzi wersja 1.7 wstrzymam się tymczasowo. Chciałbym zrobić upgrade kodu właśnie do 1.7 i dalej na nowej wersji wydawać tutorial.

 

A tak to co chcieli byście zobaczyć w następnej części tutorialu?

- Nowe rudy?

- Nowe zbroje?

- Nowe narzędzia?

- Nowe warzywa do uprawy?

- Nowe rośliny?

- Nowy łóżka?

- .......

 

Proponujcie...

 

Komentujcie...

 

PS: Liczyłem na troszkę większe zainteresowanie tematem. Więc mam prośbę, aby osoby zajmujące się tworzeniem modów lub próbujące podjąć takie wyzwanie: Umieszczajcie w tym poście screen'y z gry z tym co stworzyliście. Zaraźmy innych, nakłońmy innych do tworzenia modów....  :crazy:

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Iz0t0pic    0

Cudowny ten poradniczek, chociaż mam uczucie że żywcem wzięte z angielskiej wersji.

A poza tym, co chcę dalej...

TO!

- Nowe rudy

 

Nowe Wymiary :D

A, i to też.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
RoxiPL    2

fajne! Widać że się napracowałeś i za to like :D

przyda się :P

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!

No i dalej nie mamy nowej wersji Forge'a  :0 Pojawiła się informacja, że Forge pod 1.7 miał pojawić się na początku grudnia, ale nadal go nie ma.

Plany wydania nowych tutoriali pokrzyżowało również mi to, że urodziła mi się córeczka i mam troszkę więcej obowiązków.  :crazy:

 

Postanowiłem, że wydam kolejny tutorial pod 1.6.4. Jeszcze przed świętami powinienem go udostępnić.

 

 

 

Cudowny ten poradniczek, chociaż mam uczucie że żywcem wzięte z angielskiej wersji.

A poza tym, co chcę dalej...

TO!

- Nowe rudy

 

A, i to też.

 

Mody zaczynałem pisać ucząc się z angielskich tutorial'i. Teraz obecnie sam już pisze i rzadko kiedy opieram się o nie. Większość kodu jest mojego autorstwa, który napisałem metodą prób i błędów. Można porównać mój kod z innymi tutorial'ami i wtedy zobaczycie różnice.  :crazy:

 

Jeśli chodzi o nowy wymiar (Dimension) dodam go ale przed świętami nie zdążę. Jest to już bardzo zaawansowane programowanie i duuużo pisania  :yum:

Do świąt dodam nowe rudy tak jak chcieliście i coś jeszcze od siebie  :crazy:

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!  :crazy: 

 

Miałem stworzyć dzisiaj nową rudę, ale przez święta na życzenie znajomych dopisałem do gry kilka ciekawych elementów. Dodałem bloki żywopłotu. 

 

1qbBYr.jpg

 

TUTORIAL cz.4 - Bloki żywopłotu!

 

1. Główny plik żywopłotu

 

Tworzymy nowy plik class. Nazwiemy go "BlockFlowerLeavesMP". Tektura tego bloku to połączenie tekstury liści i kwiatów.

Będzie to sześć bloków o różnych kolorach kwiatów. Będziemy je robić z wcześniej napisanych kwiatków.

 

Zawartość pliku powinna wyglądać tak:

 

BlockFlowerLeavesMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.blocks;

import java.util.ArrayList;
import java.util.List;

import modmevipack.ModMeviPack;
import net.minecraft.block.BlockLeavesBase;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.IShearable;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class BlockFlowerLeavesMP extends BlockLeavesBase implements IShearable
{
	private static final String[] mNameHedge = new String[] {"00","01","02","03","04","05"};
	@SideOnly(Side.CLIENT)
	private Icon[] textures;
		
	public BlockFlowerLeavesMP(int par1) 
	{
		super(par1, Material.leaves, false);
		this.setCreativeTab(ModMeviPack.mTabModMeviPack);
	}
	
	public boolean isOpaqueCube()
        {
		return false;
        }

	@Override
	public boolean isShearable(ItemStack item, World world, int x, int y, int z) 
	{
		return true;
	}

	@Override
	public ArrayList<ItemStack> onSheared(ItemStack item, World world, int x, int y, int z, int fortune) 
	{
		ArrayList<ItemStack> par1 = new ArrayList<ItemStack>();
        par1.add(new ItemStack(this, 1, world.getBlockMetadata(x, y, z)));
        return par1;
	}
	
	@Override
        public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
        {
		return true;
        }
	
	@Override
        public boolean isLeaves(World world, int x, int y, int z)
        {
        return true;
        }
	
	@Override
	public int damageDropped(int meta)
	{
		return meta;
	}

	@Override
	public int getDamageValue(World world, int x, int y, int z)
	{
		return world.getBlockMetadata(x, y, z);
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public Icon getIcon(int side, int meta)
	{
		if (meta < 0 || meta >= this.textures.length) 
		{
			meta = 0;
		}
		
		return this.textures[meta];
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void getSubBlocks(int blockID, CreativeTabs creativeTabs, List list) 
	{
		for (int i = 0; i < this.mNameHedge.length; ++i) 
		{
			list.add(new ItemStack(blockID, 1, i));
		}
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void registerIcons(IconRegister iconRegister)
	{
		this.textures = new Icon[this.mNameHedge.length];

		for (int i = 0; i < this.mNameHedge.length; ++i) 
		{
			this.textures[i] = iconRegister.registerIcon("modmevipack:flowers/mHedge" + this.mNameHedge[i]);
		}
	}
}

Na samym początku widzimy:

public class BlockFlowerLeavesMP extends BlockLeavesBase implements IShearable

IShearable - dodaje do bloku funkcje związane z ścinaniem za pomocą nożyc. Ten blok będzie można zbierać tylko za pomocą nożyc.

 

Nie będę tłumaczył większości funkcji, gdyż podobne są do tych zastosowanych w class'ie kwiatów.  :innocent:

Np:

public Icon getIcon(int side, int meta)
public void getSubBlocks(int blockID, CreativeTabs creativeTabs, List list)
public void registerIcons(IconRegister iconRegister)

Nowymi funkcjami są:

@Override
public boolean isShearable(ItemStack item, World world, int x, int y, int z) 
{
	return true;
}

Ta funkcja jak jej sama nazwa wskazuje podaje do gry informacje, że blok będzie można "zbierać" za pomocą nożyc.

@Override
public ArrayList<ItemStack> onSheared(ItemStack item, World world, int x, int y, int z, int fortune) 
{
	ArrayList<ItemStack> par1 = new ArrayList<ItemStack>();
        par1.add(new ItemStack(this, 1, world.getBlockMetadata(x, y, z)));
        return par1;
}

Tutaj funkcja informuje co będzie gdy użyjemy nożyc. W tym wypadku wypadnie jeden blok naszego żywopłotu.

 

 

2. MultiBlock - podstawowy plik class

 

W paczce itemblock tworzymy nowy plik class i nazywamy go: ItemBlockFlowerLeavesMP. 

 

Jego zawartość powinna wyglądać tak:

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.itemblocks;

import net.minecraft.block.Block;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;

public class ItemBlockFlowerLeavesMP extends ItemBlock
{
	public ItemBlockFlowerLeavesMP(int par1) 
	{
		super(par1);
		this.setHasSubtypes(true);
	}
	
	@Override
	public String getUnlocalizedName(ItemStack par1)
        {
		String name = "";
		switch(par1.getItemDamage())
                {
        	case 0: 
        		{
        			name = "mHedge00";
        			break;
        		}
        	case 1: 
    			{
    				name = "mHedge01";
    				break;
    			}
        	case 2: 
    			{
    				name = "mHedge02";
    				break;
    			}
        	case 3: 
    			{
    				name = "mHedge03";
    				break;
    			}
        	case 4: 
    			{
    				name = "mHedge04";
    				break;
    			}
        	case 5: 
    			{
    				name = "mHedge05";
    				break;
    			}
        	default: name = "mHedge00";
                }
		return "modmevipack:flowers/" + name;
        }
	
	@Override
	public int getMetadata(int par1)
        {
        return par1;
        }
    
        @Override
	public Icon getIconFromDamage(int meta)
	{
		return Block.blocksList[this.itemID].getIcon(0, meta);
	}
}

Zastosowanie tego pliku jest takie same jak w przypadku kwiatów. Tłumaczyłem to w poprzedniej części poradnika.

Nie będę więc tłumaczył nic więcej.  :crazy:

 

 

3. Edytujemy plik ModFlowerMP.class

 

Musimy teraz zarejestrować nasze nowe bloki żywopłotów.

 

Plik po edycji powinien wyglądać tak:

 

ModFlowerMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.mods;

import modmevipack.blocks.BlockFlowersMP;
import modmevipack.itemblocks.ItemBlockFlowersMP;
import net.minecraft.block.Block;
import net.minecraftforge.common.MinecraftForge;
import cpw.mods.fml.common.registry.GameRegistry;

public class ModFlowersMP 
{
	public static final Block mFlowers = (new BlockFlowersMP(3000));
	public static final Block mFlowerLeaves = (new BlockFlowerLeavesMP(3005)).setHardness(0.2F).setLightOpacity(1).setStepSound(Block.soundGrassFootstep);
	
	public static void init_Flowers()
	{
		for (int i = 0; i < 16; i++ )
			MinecraftForge.addGrassPlant(mFlowers, i, 15);
		
		Block.setBurnProperties(mFlowerLeaves.blockID, 30, 60);
		
		GameRegistry.registerBlock(mFlowers, ItemBlockFlowersMP.class, (mFlowers.getUnlocalizedName().substring(5)));
		GameRegistry.registerBlock(mFlowerLeaves, ItemBlockFlowerLeavesMP.class);
		
	}
}

Pojawia się tu nowa komęda:

Block.setBurnProperties(mFlowerLeaves.blockID, 30, 60);

Oznacza ona palność bloku. Z jaką łatwością ma się zapalić i jak długo ma się palić.

 

4. Edycja pliku językowego.

 

Do pliku z językiem dopisujemy następujące linie kodu:

                LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 0), "Ciemno-niebieskie kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 1), "Zolte kwieciste kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 2), "Ciemno-fioletowe kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 3), "Jasno-fioletowe kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 4), "Czerwone kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 5), "Jasno-niebieskie kwieciste liscie");
		

Oczywiście nazwy dla naszych bloków możecie ustalić sobie sami  :crazy:

 

Na koniec ważna informacja:

Nazwę pliku class : ModFlowersMP.class zmieniamy na  ModBlocksMP.class. Wprowadziłem tą zmianę ze względu na późniejsze części tutorial'a. Ułatwi nam to pracę z większą ilością plików.

 

Nie prześle dzisiaj wam gotowego pliku źródłowego ponieważ napisałem w nim już pewne nowe rzeczy które zamierzam umieścić w kolejnej części. Zapomniałem wcześniej zrobić kopie zapasową. Mój błąd. Dlatego cały kod źródłowy zobaczycie pod koniec następnej części tutorial'a.  :0

Edytowane przez Mevistor

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!

 

No to dzisiaj już drugi poradnik dotyczący.... łóżek. Kiedyś w pewnej modyfikacji moi znajomi widzieli łóżka. Jest ona już nie aktualna, gdyż na wersje 1.4.7. Postanowiłem trochę ją odświeżyć  :crazy:

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

Zaczynamy:

 

TUTORIAL cz.5 - Nowe łóżka!

 

Dodamy w sumie 16 nowych łóżek!

 

1lJhH.jpg

 

20pWa.jpg

 

1. Zaczynamy - Główny plik łóżka

 

Tworzymy nowy plik class w paczce: blocks. Nazwiemy go: BlockBedMP

 

Zawartość tego pliku powinna wyglądać tak:

 

BlockBedMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.blocks;

import java.util.Iterator;
import java.util.Random;

import modmevipack.mods.ModItemsMP;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBed;
import net.minecraft.block.BlockDirectional;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EnumStatus;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.Direction;
import net.minecraft.util.Icon;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class BlockBedMP extends BlockDirectional
{
    public static final int[][] footBlockToHeadBlockMap = new int[][] {{0, 1}, { -1, 0}, {0, -1}, {1, 0}};
    @SideOnly(Side.CLIENT)
    private Icon[] field_94472_b;
    @SideOnly(Side.CLIENT)
    private Icon[] bedSideIcons;
    @SideOnly(Side.CLIENT)
    private Icon[] bedTopIcons;
    
    private int mNameOfBlock;
	
	public BlockBedMP(int par1, int par2) 
	{
		super(par1, Material.cloth);
		this.setBounds();
		this.mNameOfBlock = par2;
		this.disableStats();
	}
	
	@Override
        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
        {
    	if (par1World.isRemote)
        {
            return true;
        }
        else
        {
            int i1 = par1World.getBlockMetadata(par2, par3, par4);

            if (!isBlockHeadOfBed(i1))
            {
                int j1 = getDirection(i1);
                par2 += footBlockToHeadBlockMap[j1][0];
                par4 += footBlockToHeadBlockMap[j1][1];

                if (par1World.getBlockId(par2, par3, par4) != this.blockID)
                {
                    return true;
                }

                i1 = par1World.getBlockMetadata(par2, par3, par4);
            }

            if (par1World.provider.canRespawnHere() && par1World.getBiomeGenForCoords(par2, par4) != BiomeGenBase.hell)
            {
                if (isBedOccupied(i1))
                {
                    EntityPlayer entityplayer1 = null;
                    Iterator iterator = par1World.playerEntities.iterator();

                    while (iterator.hasNext())
                    {
                        EntityPlayer entityplayer2 = (EntityPlayer)iterator.next();

                        if (entityplayer2.isPlayerSleeping())
                        {
                            ChunkCoordinates chunkcoordinates = entityplayer2.playerLocation;

                            if (chunkcoordinates.posX == par2 && chunkcoordinates.posY == par3 && chunkcoordinates.posZ == par4)
                            {
                                entityplayer1 = entityplayer2;
                            }
                        }
                    }

                    if (entityplayer1 != null)
                    {
                        par5EntityPlayer.addChatMessage("tile.bed.occupied");
                        return true;
                    }

                    setBedOccupied(par1World, par2, par3, par4, false);
                }

                EnumStatus enumstatus = par5EntityPlayer.sleepInBedAt(par2, par3, par4);

                if (enumstatus == EnumStatus.OK)
                {
                    setBedOccupied(par1World, par2, par3, par4, true);
                    return true;
                }
                else
                {
                    if (enumstatus == EnumStatus.NOT_POSSIBLE_NOW)
                    {
                        par5EntityPlayer.addChatMessage("tile.bed.noSleep");
                    }
                    else if (enumstatus == EnumStatus.NOT_SAFE)
                    {
                        par5EntityPlayer.addChatMessage("tile.bed.notSafe");
                    }

                    return true;
                }
            }
            else
            {
                double d0 = (double)par2 + 0.5D;
                double d1 = (double)par3 + 0.5D;
                double d2 = (double)par4 + 0.5D;
                par1World.setBlockToAir(par2, par3, par4);
                int k1 = getDirection(i1);
                par2 += footBlockToHeadBlockMap[k1][0];
                par4 += footBlockToHeadBlockMap[k1][1];

                if (par1World.getBlockId(par2, par3, par4) == this.blockID)
                {
                    par1World.setBlockToAir(par2, par3, par4);
                    d0 = (d0 + (double)par2 + 0.5D) / 2.0D;
                    d1 = (d1 + (double)par3 + 0.5D) / 2.0D;
                    d2 = (d2 + (double)par4 + 0.5D) / 2.0D;
                }

                par1World.newExplosion((Entity)null, (double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), 5.0F, true, true);
                return true;
            }
        }
        }
    
	@Override
        @SideOnly(Side.CLIENT)
        public Icon getIcon(int par1, int par2)
        {
        if (par1 == 0)
        {
            return Block.planks.getBlockTextureFromSide(par1);
        }
        else
        {
            int k = getDirection(par2);
            int l = Direction.bedDirection[k][par1];
            int i1 = isBlockHeadOfBed(par2) ? 1 : 0;
            return (i1 != 1 || l != 2) && (i1 != 0 || l != 3) ? (l != 5 && l != 4 ? this.bedTopIcons[i1] : this.bedSideIcons[i1]) : this.field_94472_b[i1];
        }
        }
    
	@Override
        @SideOnly(Side.CLIENT)
        public void registerIcons(IconRegister par1IconRegister)
        {
    	this.bedTopIcons = new Icon[] {par1IconRegister.registerIcon("modmevipack:beds/mBedFeetTop" + this.mNameOfBlock), par1IconRegister.registerIcon("modmevipack:beds/mBedHeadTop" + this.mNameOfBlock)};
        this.field_94472_b = new Icon[] {par1IconRegister.registerIcon("modmevipack:beds/mBedFeetEnd" + this.mNameOfBlock), par1IconRegister.registerIcon("modmevipack:beds/mBedHeadEnd" + this.mNameOfBlock)};
        this.bedSideIcons = new Icon[] {par1IconRegister.registerIcon("modmevipack:beds/mBedFeetSide" + this.mNameOfBlock), par1IconRegister.registerIcon("modmevipack:beds/mBedHeadSide" + this.mNameOfBlock)};
        }
    
	@Override
        public int getRenderType()
        {
        return 14;
        }
	
	@Override
	public boolean renderAsNormalBlock()
        {
        return false;
        }
	
	@Override
	public boolean isOpaqueCube()
        {
        return false;
        }
	
	public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
        {
        this.setBounds();
        }
	
	public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
        {
        int i1 = par1World.getBlockMetadata(par2, par3, par4);
        int j1 = getDirection(i1);

        if (isBlockHeadOfBed(i1))
        {
            if (par1World.getBlockId(par2 - footBlockToHeadBlockMap[j1][0], par3, par4 - footBlockToHeadBlockMap[j1][1]) != this.blockID)
            {
                par1World.setBlockToAir(par2, par3, par4);
            }
        }
        else if (par1World.getBlockId(par2 + footBlockToHeadBlockMap[j1][0], par3, par4 + footBlockToHeadBlockMap[j1][1]) != this.blockID)
        {
            par1World.setBlockToAir(par2, par3, par4);

            if (!par1World.isRemote)
            {
                this.dropBlockAsItem(par1World, par2, par3, par4, i1, 0);
            }
        }
        }
	
	@Override
	public int idDropped(int par1, Random par2Random, int par3)
        {
		return isBlockHeadOfBed(par1) ? 0 : CheckItemID(this.mNameOfBlock);
        }
	
	private void setBounds()
        {
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5625F, 1.0F);
        }
	
	public static boolean isBlockHeadOfBed(int par0)
        {
        return (par0 & 8) != 0;
        }
	
	public static boolean isBedOccupied(int par0)
        {
        return (par0 & 4) != 0;
        }
	
	public static void setBedOccupied(World par0World, int par1, int par2, int par3, boolean par4)
        {
        int l = par0World.getBlockMetadata(par1, par2, par3);

        if (par4)
        {
            l |= 4;
        }
        else
        {
            l &= -5;
        }

        par0World.setBlockMetadataWithNotify(par1, par2, par3, l, 4);
        }
	
	public static ChunkCoordinates getNearestEmptyChunkCoordinates(World par0World, int par1, int par2, int par3, int par4)
        {
        int i1 = par0World.getBlockMetadata(par1, par2, par3);
        int j1 = BlockDirectional.getDirection(i1);

        for (int k1 = 0; k1 <= 1; ++k1)
        {
            int l1 = par1 - footBlockToHeadBlockMap[j1][0] * k1 - 1;
            int i2 = par3 - footBlockToHeadBlockMap[j1][1] * k1 - 1;
            int j2 = l1 + 2;
            int k2 = i2 + 2;

            for (int l2 = l1; l2 <= j2; ++l2)
            {
                for (int i3 = i2; i3 <= k2; ++i3)
                {
                    if (par0World.doesBlockHaveSolidTopSurface(l2, par2 - 1, i3) && !par0World.getBlockMaterial(l2, par2, i3).isOpaque() && !par0World.getBlockMaterial(l2, par2 + 1, i3).isOpaque())
                    {
                        if (par4 <= 0)
                        {
                            return new ChunkCoordinates(l2, par2, i3);
                        }

                        --par4;
                    }
                }
            }
        }

        return null;
        }
	
	@Override
	public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7)
        {
        if (!isBlockHeadOfBed(par5))
        {
        	ItemStack ret = new ItemStack(idDropped(par5, par1World.rand, par7), 1, 0);
    		this.dropBlockAsItem_do(par1World, par2, par3, par4, ret);
        }
        }
	
	@Override
	public int getMobilityFlag()
        {
        return 1;
        }
	
	@Override
	@SideOnly(Side.CLIENT)
	public int idPicked(World par1World, int par2, int par3, int par4)
        {
		return CheckItemID(this.mNameOfBlock);
        }
	
	public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer)
        {
        if (par6EntityPlayer.capabilities.isCreativeMode && isBlockHeadOfBed(par5))
        {
            int i1 = getDirection(par5);
            par2 -= footBlockToHeadBlockMap[i1][0];
            par4 -= footBlockToHeadBlockMap[i1][1];

            if (par1World.getBlockId(par2, par3, par4) == this.blockID)
            {
                par1World.setBlockToAir(par2, par3, par4);
            }
        }
        }
	
	public int CheckItemID(int par1)
	{
		switch (par1) 
		{
			case 0 : return ModItemsMP.mBedI00.itemID;
			case 1 : return ModItemsMP.mBedI01.itemID;
			case 2 : return ModItemsMP.mBedI02.itemID;
			case 3 : return ModItemsMP.mBedI03.itemID;
			case 4 : return ModItemsMP.mBedI04.itemID;
			case 5 : return ModItemsMP.mBedI05.itemID;
			case 6 : return ModItemsMP.mBedI06.itemID;
			case 7 : return ModItemsMP.mBedI07.itemID;
			case 8 : return ModItemsMP.mBedI08.itemID;
			case 9 : return ModItemsMP.mBedI09.itemID;
			case 10 : return ModItemsMP.mBedI10.itemID;
			case 11 : return ModItemsMP.mBedI11.itemID;
			case 12 : return ModItemsMP.mBedI12.itemID;
			case 13 : return ModItemsMP.mBedI13.itemID;
			case 14 : return ModItemsMP.mBedI14.itemID;
			case 15 : return ModItemsMP.mBedI15.itemID;
			default : return ModItemsMP.mBedI00.itemID;
		}
	}
	
	@Override
	public boolean isBed(World world, int x, int y, int z, EntityLivingBase player)
        {
        return true;
        }
	
	@Override
	public ChunkCoordinates getBedSpawnPosition(World world, int x, int y, int z, EntityPlayer player)
        {
        return BlockBed.getNearestEmptyChunkCoordinates(world, x, y, z, 0);
        }
}

Do stworzenia tego plików wykorzystałem główny plik łóżka z gry. Przerobiłem go troszkę pod moje potrzeby.

 

Opiszmy troszkę ten plik:

public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)

Funkcja ta odpowiada za to co się stanie gdy klikniemy prawym przyciskiem myszy na nasze łóżko. W tym wypadku pójdziemy spać.

public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)

Funkcja ta kontroluje okoliczne bloki. Gdy któryś zniszczymy sprawdza czy łóżko może dalej istniej. W związku z tym, że łóżko zajmuje dwa bloki, to dzięki tej funkcji gdy zniszczymy któryś z nich, całe łóżko zostanie zniszczone.

 

Jest to dosyć zawiła class'a. Żeby ją zrozumieć trzeba dobrze wczytać się w kod. Dla znających angielski będzie to dużo prostsze. 

 

 

2. Item - Główny plik item'ków

 

Jako że łóżko zajmuje dwa bloki, nie możemy go przechowywać w jednym slocie w ekwipunku. Musimy napisać item do naszego łóżka.

Tworzymy nowy plik class: ItemBedMP w paczce items. Musimy tą paczkę najpierw utworzyć. Mam nadzieje że pamiętacie jak to się robiło.

 

Zawartość pliku:

 

ItemBedMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.items;

import modmevipack.ModMeviPack;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;

public class ItemBedMP extends Item
{
	private int mNameOfBlock;
	
	public ItemBedMP(int par1, int par2) 
	{
		super(par1);
		this.mNameOfBlock = par2;
		this.setCreativeTab(ModMeviPack.mTabModMeviPack);
	}

	@Override
	public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
    {
        if (par3World.isRemote)
        {
            return true;
        }
        else if (par7 != 1)
        {
            return false;
        }
        else
        {
            ++par5;            
            
            int i1 = MathHelper.floor_double((double)(par2EntityPlayer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
            byte b0 = 0;
            byte b1 = 0;

            if (i1 == 0)
            {
                b1 = 1;
            }

            if (i1 == 1)
            {
                b0 = -1;
            }

            if (i1 == 2)
            {
                b1 = -1;
            }

            if (i1 == 3)
            {
                b0 = 1;
            }

            if (par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack) && par2EntityPlayer.canPlayerEdit(par4 + b0, par5, par6 + b1, par7, par1ItemStack))
            {
                if (par3World.isAirBlock(par4, par5, par6) && par3World.isAirBlock(par4 + b0, par5, par6 + b1) && par3World.doesBlockHaveSolidTopSurface(par4, par5 - 1, par6) && par3World.doesBlockHaveSolidTopSurface(par4 + b0, par5 - 1, par6 + b1))
                {
                    par3World.setBlock(par4, par5, par6, this.mNameOfBlock, i1, 3);

                    if (par3World.getBlockId(par4, par5, par6) == this.mNameOfBlock)
                    {
                        par3World.setBlock(par4 + b0, par5, par6 + b1, this.mNameOfBlock, i1 + 8, 3);
                    }

                    --par1ItemStack.stackSize;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
    }	
}

Najważniejsza funkcja w tej class'ie:

public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)

Odpowiada ona za powstanie łóżka w świecie. Gdy klikniemy item'kiem na ziemi, on zniknie i powstanie w tym miejscu łóżko.

 

 

3. Edycja pliku językowego

 

Najprostsze co może być. Dopisujemy do pliku parę lini kodu, tak żeby wyglądało to tak:

 

LanguageMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.language;

import modmevipack.mods.ModBlocksMP;
import modmevipack.mods.ModItemsMP;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.registry.LanguageRegistry;

public class LanguageMP 
{	
	public static void init_Language()
	{
		LanguageRegistry.instance().addStringLocalization("itemGroup.ModMeviPack0", "Mod MeviPack 1.2.0");
		
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 0), "Niebieska chryzantema");	
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 1), "Zolta chryzantema");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 2), "Fioletowa chryzantema");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 3), "Czerwona chryzantema");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 4), "Czerwony fiolek");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 5), "Zolty fiolek");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 6), "Niebieski fiolek");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 7), "Fioletowy fiolek");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 8), "Czerwona azjatycka roza");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 9), "Zolta azjatycka roza");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 10), "Czerwona stokrotka");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 11), "Niebieska stokrotka");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 12), "Fioletowa stokrotka");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 13), "Pierwiosnek rozowy");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 14), "Czerwona lilia");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowers, 1, 15), "Niebieska lilia");
		
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 0), "Ciemno-niebieskie kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 1), "Zolte kwieciste kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 2), "Ciemno-fioletowe kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 3), "Jasno-fioletowe kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 4), "Czerwone kwieciste liscie");
		LanguageRegistry.addName(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 5), "Jasno-niebieskie kwieciste liscie");
		
		LanguageRegistry.addName(ModItemsMP.mBedI00, "Creeper'owe lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI01, "Krowkowe lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI02, "Magmowe lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI03, "Ederman'owe lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI04, "Ciemno-niebieskie lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI05, "Jasno-niebieskie lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI06, "Zolte lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI07, "Jasno-zielone lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI08, "Pomaranczowe lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI09, "Jasno-fioletowe lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI10, "Czarne lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI11, "Ciemno-szare lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI12, "Jasno-szare lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI13, "Brazowe lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI14, "Ciemno-zielone lozko");
		LanguageRegistry.addName(ModItemsMP.mBedI15, "Muchomorkowe lozko");
		
		LanguageRegistry.addName(ModBlocksMP.mBed00, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed01, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed02, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed03, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed04, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed05, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed06, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed07, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed08, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed09, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed10, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed11, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed12, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed13, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed14, "Lozko");
		LanguageRegistry.addName(ModBlocksMP.mBed15, "Lozko");
	}
}

4. Rejestrowanie bloków

 

No i oczywiście nasze bloki łóżek trzeba zarejestrować w grze. 

Otwieramy class'e ModBlockMP i edytujemy ją. Dopisujemy do niej parę rzeczy tak żeby wyglądał w ten sposób:

 

ModBlockMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.mods;

import modmevipack.blocks.BlockBedMP;
import modmevipack.blocks.BlockFlowerLeavesMP;
import modmevipack.blocks.BlockFlowerMP;
import modmevipack.itemblocks.ItemBlockFlowerLeavesMP;
import modmevipack.itemblocks.ItemBlockFlowersMP;
import net.minecraft.block.Block;
import net.minecraftforge.common.MinecraftForge;
import cpw.mods.fml.common.registry.GameRegistry;

public class ModBlocksMP 
{
	public static final Block mFlowers = (new BlockFlowerMP(3000)).setHardness(0.0F).setStepSound(Block.soundGrassFootstep);
	public static final Block mFlowerLeaves = (new BlockFlowerLeavesMP(3005)).setHardness(0.2F).setLightOpacity(1).setStepSound(Block.soundGrassFootstep);
	
	public static final Block mBed00 = (new BlockBedMP(3100, 0)).setHardness(0.2F).setUnlocalizedName("mBed00").setTextureName("modmevipack:beds/mBed00");
	public static final Block mBed01 = (new BlockBedMP(3101, 1)).setHardness(0.2F).setUnlocalizedName("mBed01").setTextureName("modmevipack:beds/mBed01");
	public static final Block mBed02 = (new BlockBedMP(3102, 2)).setHardness(0.2F).setUnlocalizedName("mBed02").setTextureName("modmevipack:beds/mBed02");
	public static final Block mBed03 = (new BlockBedMP(3103, 3)).setHardness(0.2F).setUnlocalizedName("mBed03").setTextureName("modmevipack:beds/mBed03");
	public static final Block mBed04 = (new BlockBedMP(3104, 4)).setHardness(0.2F).setUnlocalizedName("mBed04").setTextureName("modmevipack:beds/mBed04");
	public static final Block mBed05 = (new BlockBedMP(3105, 5)).setHardness(0.2F).setUnlocalizedName("mBed05").setTextureName("modmevipack:beds/mBed05");
	public static final Block mBed06 = (new BlockBedMP(3106, 6)).setHardness(0.2F).setUnlocalizedName("mBed06").setTextureName("modmevipack:beds/mBed06");
	public static final Block mBed07 = (new BlockBedMP(3107, 7)).setHardness(0.2F).setUnlocalizedName("mBed07").setTextureName("modmevipack:beds/mBed07");
	public static final Block mBed08 = (new BlockBedMP(3108, 8)).setHardness(0.2F).setUnlocalizedName("mBed08").setTextureName("modmevipack:beds/mBed08");
	public static final Block mBed09 = (new BlockBedMP(3109, 9)).setHardness(0.2F).setUnlocalizedName("mBed09").setTextureName("modmevipack:beds/mBed09");
	public static final Block mBed10 = (new BlockBedMP(3110, 10)).setHardness(0.2F).setUnlocalizedName("mBed10").setTextureName("modmevipack:beds/mBed10");
	public static final Block mBed11 = (new BlockBedMP(3111, 11)).setHardness(0.2F).setUnlocalizedName("mBed11").setTextureName("modmevipack:beds/mBed11");
	public static final Block mBed12 = (new BlockBedMP(3112, 12)).setHardness(0.2F).setUnlocalizedName("mBed12").setTextureName("modmevipack:beds/mBed12");
	public static final Block mBed13 = (new BlockBedMP(3113, 13)).setHardness(0.2F).setUnlocalizedName("mBed13").setTextureName("modmevipack:beds/mBed13");
	public static final Block mBed14 = (new BlockBedMP(3114, 14)).setHardness(0.2F).setUnlocalizedName("mBed14").setTextureName("modmevipack:beds/mBed14");
	public static final Block mBed15 = (new BlockBedMP(3115, 15)).setHardness(0.2F).setUnlocalizedName("mBed15").setTextureName("modmevipack:beds/mBed15");
	
	public static void init_BlocksMP()
	{
		for (int i = 0; i < 16; i++ )
			MinecraftForge.addGrassPlant(mFlowers, i, 15);
		
		Block.setBurnProperties(mFlowerLeaves.blockID, 30, 60);
		
		GameRegistry.registerBlock(mFlowers, ItemBlockFlowersMP.class);
		GameRegistry.registerBlock(mFlowerLeaves, ItemBlockFlowerLeavesMP.class);
		
		GameRegistry.registerBlock(mBed00);
		GameRegistry.registerBlock(mBed01);
		GameRegistry.registerBlock(mBed02);
		GameRegistry.registerBlock(mBed03);
		GameRegistry.registerBlock(mBed04);
		GameRegistry.registerBlock(mBed05);
		GameRegistry.registerBlock(mBed06);
		GameRegistry.registerBlock(mBed07);
		GameRegistry.registerBlock(mBed08);
		GameRegistry.registerBlock(mBed09);	
		GameRegistry.registerBlock(mBed10);	
		GameRegistry.registerBlock(mBed11);	
		GameRegistry.registerBlock(mBed12);	
		GameRegistry.registerBlock(mBed13);	
		GameRegistry.registerBlock(mBed14);	
		GameRegistry.registerBlock(mBed15);
	}
}

Musimy również zarejestrować nasz item'ki. Jest to troszkę łatwiejsze niż bloki.

W paczce mods tworzymy nową klasę i nazywamy ją ModItemsMP.

 

Zawartość jej:

 

ModItemsMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.mods;

import modmevipack.items.ItemBedMP;
import net.minecraft.item.Item;

public class ModItemsMP 
{
	public static final Item mBedI00 = (new ItemBedMP(3120, ModBlocksMP.mBed00.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI00").setTextureName("modmevipack:beds/mBedI00");
	public static final Item mBedI01 = (new ItemBedMP(3121, ModBlocksMP.mBed01.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI01").setTextureName("modmevipack:beds/mBedI01");
	public static final Item mBedI02 = (new ItemBedMP(3122, ModBlocksMP.mBed02.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI02").setTextureName("modmevipack:beds/mBedI02");
	public static final Item mBedI03 = (new ItemBedMP(3123, ModBlocksMP.mBed03.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI03").setTextureName("modmevipack:beds/mBedI03");
	public static final Item mBedI04 = (new ItemBedMP(3124, ModBlocksMP.mBed04.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI04").setTextureName("modmevipack:beds/mBedI04");
	public static final Item mBedI05 = (new ItemBedMP(3125, ModBlocksMP.mBed05.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI05").setTextureName("modmevipack:beds/mBedI05");
	public static final Item mBedI06 = (new ItemBedMP(3126, ModBlocksMP.mBed06.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI06").setTextureName("modmevipack:beds/mBedI06");
	public static final Item mBedI07 = (new ItemBedMP(3127, ModBlocksMP.mBed07.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI07").setTextureName("modmevipack:beds/mBedI07");
	public static final Item mBedI08 = (new ItemBedMP(3128, ModBlocksMP.mBed08.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI08").setTextureName("modmevipack:beds/mBedI08");
	public static final Item mBedI09 = (new ItemBedMP(3129, ModBlocksMP.mBed09.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI09").setTextureName("modmevipack:beds/mBedI09");
	public static final Item mBedI10 = (new ItemBedMP(3130, ModBlocksMP.mBed10.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI10").setTextureName("modmevipack:beds/mBedI10");
	public static final Item mBedI11 = (new ItemBedMP(3131, ModBlocksMP.mBed11.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI11").setTextureName("modmevipack:beds/mBedI11");
	public static final Item mBedI12 = (new ItemBedMP(3132, ModBlocksMP.mBed12.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI12").setTextureName("modmevipack:beds/mBedI12");
	public static final Item mBedI13 = (new ItemBedMP(3133, ModBlocksMP.mBed13.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI13").setTextureName("modmevipack:beds/mBedI13");
	public static final Item mBedI14 = (new ItemBedMP(3134, ModBlocksMP.mBed14.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI14").setTextureName("modmevipack:beds/mBedI14");
	public static final Item mBedI15 = (new ItemBedMP(3135, ModBlocksMP.mBed15.blockID)).setMaxStackSize(1).setUnlocalizedName("mBedI15").setTextureName("modmevipack:beds/mBedI15");

	public static void init_ItemsMP()
	{
			
	}
}
 

Nic chyba dodać i nic chyba ująć  :crazy:

 

5. Kończymy

 

Cała struktura naszego drzewka pików powinna teraz wyglądać tak:

 

3.jpg

 

Zamieszczam tutaj kod źródłowy, wraz z grafikami:

Zaloguj lub zarejestruj się aby zobaczyć ten link.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!

 

Prosiliście o nową rudę. Więc dodamy ją w dzisiejszej części.

 

1Cjgax.jpg

 

Zaczynamy:

 

TUTORIAL cz.6 - Nowa ruda!

 

1. Tworzymy nowe pliki class i nową paczkę (package).

 

Tworzymy nową paczkę (package) i nazywamy ją "generators".

Następnie w utworzonej paczce tworzymy plik class i nazywamy go "GenMagicOreMP". Wszystkie pliki generatorów postanowiłem tworzyć w tej paczce i nazywać je przedrostkiem "Gen". Pliki te to nic innego jak skrypty odpowiedzialne za generowanie "rzeczy" w świecie MInecraft, np: bloki, kwiaty, drzewa, itp..

Następnie w naszej paczce "blocks" tworzymy kolejny plik class i nazywamy go "BlockMagicOreMP". Będzie to plik z naszym nowym blokiem rudy.

Trzeci plik jaki stworzymy to plik class w paczce "mods". Nazwiemy go "ModGeneratorsMP". Będziemy tu rejestrować wszystkie nasze generatory. Generatory muszą być tak samo zarejestrowane w grze jak bloki.

 

Całość nowych plików powinna wyglądać tak:

2HM05F.jpg

 

 

2. Główny plik naszego bloku rudy.

 

Przechodzimy do pliku "BlockMagicOreMP". Jak już wspomniałem jest to główny plik naszego bloku rudy.

Całość pliku powinna wyglądać tak:

 

BlockMagicOreMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.blocks;

import modmevipack.ModMeviPack;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;

public class BlockMagicOreMP extends Block
{
	public BlockMagicOreMP(int par1) 
	{
		super(par1, Material.rock);
		this.setCreativeTab(ModMeviPack.mTabModMeviPack);
	}
}

Bardzo prosta budowa  :crazy:  Nic chyba nie muszę tłumaczyć.

 

 

3. Główny plik naszego generatora.

 

Przechodzimy do pliku "GenMagicOreMP".

Zawartość pliku:

 

GenMagicOreMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.generators;

import java.util.Random;

import modmevipack.mods.ModBlocksMP;
import net.minecraft.block.Block;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenMinable;
import cpw.mods.fml.common.IWorldGenerator;

public class GenMagicOreMP implements IWorldGenerator
{
	@Override
	public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) 
	{
	 if (world.provider.dimensionId == 0) generateSurface(world, random, chunkX * 16, chunkZ * 16); 
	}
	
	private void generateSurface(World world, Random random, int x, int z)
	{
		this.addOreSpawn(ModBlocksMP.mMagicOre, world, random, x, z, 16, 16, 2 + random.nextInt(7), 5, 15, 30);	
	}
	
	public void addOreSpawn(Block block, World world, Random random, int blockXPos, int blockZPos, int maxX, int maxZ, int maxVeinSize, int chancesToSpawn, int minY, int maxY)
	{
		int maxPossY = minY + (maxY - 1);

		int diffBtwnMinMaxY = maxY - minY;
		for (int x = 0; x < chancesToSpawn; x++)
		{
			int posX = blockXPos + random.nextInt(maxX);
			int posY = minY + random.nextInt(diffBtwnMinMaxY);
			int posZ = blockZPos + random.nextInt(maxZ);
			(new WorldGenMinable(block.blockID, maxVeinSize)).generate(world, random, posX, posY, posZ);
		}
	}
}

A więc:

public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) 

Procedura ta jest wywoływana wraz ze startem generatora. Zawarta w niej funkcja odpowiada aby nasz blok był generowany tylko na głównym świecie "(world.provider.dimensionId == 0)".

public void addOreSpawn(Block block, World world, Random random, int blockXPos, int blockZPos, int maxX, int maxZ, int maxVeinSize, int chancesToSpawn, int minY, int maxY)

Procedura generująca naszą rude. Najważniejsze parametry w niej zawarte to:

block - nasz blok naszej rudy

blockXPos - współrzędna X

blockZPos - współrzędna Y

maxX / maxZ - 16 i 16 określa że nasza ruda będzie występować na cały chunk'u - rozmiar chunk'a to 16 na 16.

maxVeinSize - ilość bloków naszej rudy występujących w jednej żyle rudy (obok siebie)

chancesToSpawn - ilość żył naszej rudy występujących w jednym chunk'u

minY / maxY - minimalna i maksymalna wysokość występowania naszej rudy

 

 

4. Rejestracja naszego generatora

 

Otwieramy plik class o nazwie "ModGeneratorsMP".

Jego zawartość:

 

Mod GeneratorsMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.mods;

import modmevipack.generators.GenMagicOreMP;
import cpw.mods.fml.common.registry.GameRegistry;

public class ModGeneratorsMP 
{
	public static void init_GeneratorsMP()
	{
		GameRegistry.registerWorldGenerator(new GenMagicOreMP());
	}
}

W tym pliku rejestrujemy nasz generator. Tutaj będziemy rejestrowali oczywiście też inne nasze generatory, np: do kwiatów.

 

 

5. Edycja głównego pliku modyfikacji.

 

Otwieramy główny plik naszej modyfikacji "ModMeviPack.class". Następnie w procedurze "Load" dopisujemy taki oto kod:

ModGeneratorsMP.init_GeneratorsMP();

6. Plik językowy.

 

W pliku językowym musimy dodać jeszcze nazwę naszego bloku rudy. Dopisujemy:

LanguageRegistry.addName(ModBlocksMP.mMagicOre, "Magiczna ruda");

Całość kodu oraz grafika rudy znajduje się tutaj:

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

Dziękuje i pozdrawiam.

Mevistor

Edytowane przez Mevistor

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!

 

Już dawno powinienem stworzyć tą część tutorial'a, gdyż jest niezbędna do grania w trybie survival. Stworzymy dzisiaj generator naszych kwiatów w świecie Minecraft'a  :crazy:

 

169CU4.jpg

 

2Oit02.jpg

 

TUTORIAL cz.7 - Generator

 

 

1. Główny plik naszego generatora.

 

W paczce "generators" tworzymy nowi plik class i nazywamy go "GenFlowersMP". 

Zawartość pliku:

 

GenFlowersMP.class

package modmevipack.generators;

import java.util.Random;

import modmevipack.mods.ModBlocksMP;
import net.minecraft.block.Block;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenerator;
import cpw.mods.fml.common.IWorldGenerator;

public class GenFlowersMP implements IWorldGenerator
{
	@Override
	public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) 
	{
		if (world.provider.dimensionId == 0) generateSurface(world, random, chunkX * 16, chunkZ * 16); 
	}
	
	public void generateSurface(World world, Random random, int x,int z)
	{
		for(int k = 0; k < 20; k++)
		{
			int randPosX = x + random.nextInt(16) + 8;
			int randPosY = random.nextInt(128);
			int randPosZ = z + random.nextInt(16) + 8;
			(new XGenFlowersMP()).generate(world, random, randPosX, randPosY, randPosZ);
		}
	}
}

class XGenFlowersMP extends WorldGenerator 
{
	@Override
	public boolean generate(World world, Random random, int i, int j, int k) 
	{
		int par1 = random.nextInt(17);
		
		for (int l = 0; l < 64; ++l)
		{
            int i1 = i + random.nextInt(8) - random.nextInt(8);
            int j1 = j + random.nextInt(4) - random.nextInt(4);
            int k1 = k + random.nextInt(8) - random.nextInt(8);

            if (world.isAirBlock(i1, j1, k1) && (!world.provider.hasNoSky || j1 < 128) && Block.blocksList[ModBlocksMP.mFlowers.blockID].canBlockStay(world, i1, j1, k1))
            {
            	world.setBlock(i1, j1, k1, ModBlocksMP.mFlowers.blockID, par1, 2);
            }
        }
        return true;
	}
}

Troszkę teorii dla osób piszących w javie. W tym pliku widzimy dwie klasy (class). Większość osób tworzy każdą klasę w nowym pliku. Ja mam dziwną manię tworzenia wszystkiego w jednym. Przypominam tylko, że każda następna klasa w tym samym pliku nie może być "public" - piszemy samo słowo class.

 

Początek naszego pliku zaczyna się prawie identycznie jak w przypadku generatora zawartego w poprzednim tutorial'u.

Nie mamy praktycznie żadnej różnicy, ale dalej widzimy nową klasę (class). Poprzednio odwołaliśmy się do już gotowej klasy w grze. Tym razem stworzymy naszą - nową klasę generatora.

public boolean generate(World world, Random random, int i, int j, int k) 
	{
		int par1 = random.nextInt(17);
		
		for (int l = 0; l < 64; ++l)
		{
            int i1 = i + random.nextInt(8) - random.nextInt(8);
            int j1 = j + random.nextInt(4) - random.nextInt(4);
            int k1 = k + random.nextInt(8) - random.nextInt(8);

            if (world.isAirBlock(i1, j1, k1) && (!world.provider.hasNoSky || j1 < 128) && Block.blocksList[ModBlocksMP.mFlowers.blockID].canBlockStay(world, i1, j1, k1))
            {
            	world.setBlock(i1, j1, k1, ModBlocksMP.mFlowers.blockID, par1, 2);
            }
        }
        return true;
	}

Co tu dużo tłumaczyć. Funkcja losuje najpierw typ kwiatka (pamiętamy że w kwiatkach istniała wartość "meta" i to właśnie ją losujemy). Następnie losuje rozrzut kwiatka w danym punkcje. Może być obok siebie np: 4 kwiaty, a może być 6.

 

worls.isAirBlock - sprawdza czy blok jest powietrzem (czy nic tu nie ma) 

world.provider.hasNoSky - sprawdza czy blok jest poniżej 128 bloków wysokości - powyżej zaczyna się niebo ;)

 

Dalej jest jeszcze dyrektywa która sprawdza czy blok może stać w danym miejscu. Odwołuje się ona do pliku kwiatka.

Jeśli te warunki zostaną spełnione, tworzymy blok kwiatu w danym miejscu.

 

 

2. Rejestrowanie generatora

 

Pozostało nam tylko zarejestrować generator. Otwieramy plik "ModGeneratorsMP" i dopisujemy w nim deklaracje rejestrującą kolejny generator.

GameRegistry.registerWorldGenerator(new GenFlowersMP());

Całość gotowa!  :crazy:

 

Oto kod źródłowy:

Zaloguj lub zarejestruj się aby zobaczyć ten link.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!

 

Dzisiaj dodam krótki tutorial dotyczący receptur do CraftBox's.

 

1jypY.jpg

 

 

TUTORIAL cz.8 - Receptury

 

 

1. Tworzymy receptury!

 

W paczce "mods" tworzymy nowy plik class i nazywamy go "ModRecipes". W tym pliku będziemy umieszczać wszystkie receptury crafting'u.

Zawartość pliku:

 

ModRecipes.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.mods;

import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.registry.GameRegistry;

public class ModRecipes 
{
	public static void init_Recipes()
	{
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 0), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 0), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 1), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 1), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 2), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 2), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 4), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 3), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 4), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 4), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 1), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 5), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 5), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 6), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 2), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 7), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 4), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 8), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 1), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 9), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 4), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 10), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 0), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 11), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 3), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 12), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 3), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 13), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 4), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 14), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		GameRegistry.addRecipe(new ItemStack(ModBlocksMP.mFlowerLeaves, 1, 0), new Object[]{"ABA", Character.valueOf('A'), new ItemStack(ModBlocksMP.mFlowers, 1, 15), Character.valueOf('B'), new ItemStack(Block.leaves, 1),});
		
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI00, 1), new Object[]{ "BAB", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Item.gunpowder, 1),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI01, 1), new Object[]{ "BAB", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Item.leather, 1),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI02, 1), new Object[]{ "BAB", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Item.magmaCream, 1),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI03, 1), new Object[]{ "BAB", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Item.enderPearl, 1),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI04, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 11),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI05, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 3),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI06, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 4),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI07, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 5),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI08, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 1),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI09, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 2),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI10, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 15),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI11, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 7),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI12, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 8),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI13, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 12),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI14, 1), new Object[]{ "B", "A", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.cloth, 1, 13),});
		GameRegistry.addRecipe(new ItemStack(ModItemsMP.mBedI15, 1), new Object[]{ "BAB", Character.valueOf('A'), new ItemStack(Item.bed, 1), Character.valueOf('B'), new ItemStack(Block.mushroomRed, 1),});
	}
}

Ustaliliśmy tu receptury do tworzenia bloków żywopłotu i bloków łóżek.

Wszystkie linijki rejestrowania procedur są prawie takie same. Można zapisać to ogólnym wzorem:

 

GameRegistry.addRecipes(new ItemStack(otrzymany przedmiot, ilość, meta dane), new Object[]{ " ułożenie w CraftBox'ie ", Character.valueOf('litera do której zaraz przypiszemy przedmiot'), new ItemStack(nazwa przedmiotu, ilość, meta data), Charact..... itd..... });

 

ułożenie w CraftBox'ie wygląda tak:

 

X X X

X Y X

X X X

 

czyli zapiszemy to tak "XXX, XYX, XXX".

 

Całość kodu:

Zaloguj lub zarejestruj się aby zobaczyć ten link.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!

 

Po dłuższej przerwie dzisiaj napiszemy tutorial o nowy plantacjach. Dodamy Truskawki i Jagody!  :crazy:

 

1dA4OL.png

 

TUTORIAL cz. 9 - Nowe plantacje.

 

 

1. Główne pliki jagody i truskawek.

 

Zaczniemy od stworzenia nowej paczki, którą nazwiemy: "modmevipack.blocks.plants". Będziemy umieszczać w niej wszystkie nowe warzywa i owoce które dodamy do gry. Następnie w tej paczce tworzymy nowy plik class i nazywamy go: "BlockBlueberryMP".

 

Zawartość pliku:

 

BlockBlueberryMP.java

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.blocks.plants;

import java.util.Random;

import modmevipack.mods.ModItemsMP;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCrops;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;
import net.minecraft.world.World;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class BlockBlueberryMP extends BlockCrops
{
	@SideOnly(Side.CLIENT)
	public static Icon[] iconArray;
	
	public BlockBlueberryMP(int par1) 
	{
		super(par1);
	}
	
	@Override
	public boolean canBlockStay(World par1World, int par2, int par3, int par4)
	{
		int par5 = par1World.getBlockId(par2, par3 - 1, par4);
		
		return par5 == Block.tilledField.blockID || par5 == Block.grass.blockID || par5 == Block.dirt.blockID;
        }
	
	@Override
	public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7) 
	{	
		ItemStack ret = new ItemStack(idDropped(par5, par1World.rand, par7), quantityDropped(par5, 0, par1World.rand), 0);
		this.dropBlockAsItem_do(par1World, par2, par3, par4, ret);
        }
	
	@Override
	public boolean onBlockActivated(World world, int i, int j, int k, EntityPlayer entity, int l, float m, float n, float o)
	{
		int par1 = world.getBlockMetadata(i, j, k);
		if ( par1 > 6 ) 
		{
			this.dropBlockAsItemWithChance(world, i, j, k, par1, 1.0F, 0);
			world.setBlockMetadataWithNotify(i, j, k, 0, 2);
			return true;
		} 
		else 
		{
			return false;
		}
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public Icon getIcon(int par1, int par2)
	{
		if (par2 > 6) 
		{
			return this.iconArray[2];	
		}
		else if (par2 < 3)
		{
			return this.iconArray[0];
		} 
		else 
		{
			return this.iconArray[1];
		}
	}
	
	@Override
	public int idDropped(int par1, Random par2Random, int par3)
	{
		if (par1 > 6) 
		{
			return getCropItem();
		} 
		else 
		{
			return getSeedItem();
		}
	}
	
	@Override
	public int quantityDropped(int par1, int fortune, Random random) 
	{
		if (par1 > 6 ) 
		{
	    	int i = random.nextInt(3) + 1;
	    	return i;
	    } 
		else 
		{
	    	return 1;
	    }
	}
	
	@Override
	protected int getSeedItem() 
	{
		return ModItemsMP.mPlantSeeds.itemID;
	}
	 
	@Override
	protected int getCropItem() 
	{
		return ModItemsMP.mVegFruBlueberry.itemID;
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void registerIcons(IconRegister par1IconRegister)
	{
		this.iconArray = new Icon[3];
		
		for (int i = 0; i < this.iconArray.length; ++i)
		{
			this.iconArray[i] = par1IconRegister.registerIcon("modmevipack:plants/mBlueberry" + i);
		}
	}
}

Rozszerzenie "BlockCrops" informuje grę, iż jest to blok który da się uprawiać. Jest to bardzo istotne, gdyż nasze roślinki muszą rosnąć, tak jak np: pszenica czy marchewka.

public boolean canBlockStay(World par1World, int par2, int par3, int par4)

Tej procedury chyba nie muszę tłumaczyć. Chodzi tutaj o podłoże na jakim może nasz blok rosnąć. W tym wypadku chodzi o ziemię, trawę i pole uprawne.

public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7) 

Ta procedura odpowiada za wyrzucenie z naszego bloku przedmiotów, np: gdy zniszczymy nasz blok to ta procedura zostanie wywołana.

public boolean onBlockActivated(World world, int i, int j, int k, EntityPlayer entity, int l, float m, float n, float o)

No i tu bardzo ciekawa procedura. Każdy blok rosnąc zwiększa swoją wartość "meta". 0 (zero) oznacza że blok jest dopiero posadzony i zaczyna się cykl wzrostu. 7 (siedem) oznacza że nasz blok jest już dojrzały. Wartość ta jest dodawana losowo. Dzięki temu  każda roślina rośnie indywidualnie. Możemy zaobserwować to np: na bloku pszenicy.

Powyższa procedura odpowiada za kliknięcie prawego przycisku myszy. Gdy blok jest dojrzały i klikniemy na niego prawym przyciskiem myszy to zerwiemy jagody/truskawki z krzaka i cykl wzrostu wróci do wartości 2 (dwa). 

public Icon getIcon(int par1, int par2)

Dzięki tej funkcji możemy podziwiać etapy wzrostu. Na podstawie wartości "meta" ustalany jest wygląd naszego bloku.

public int idDropped(int par1, Random par2Random, int par3)

Określamy tutaj jaki przedmiot zostanie wyrzucony z bloku gdy np: go zniszczymy lub klikniemy prawym przyciskiem myszy. Znów się kłania wartość "meta".

public int quantityDropped(int par1, int fortune, Random random) 

Ilość wyrzuconych przedmiotów.

protected int getSeedItem() 

Nasionko naszej rośliny

protected int getCropItem()

Owoc naszej rośliny.

 

Podobnie tworzymy drugi plik class. Nazwiemy go sobie "BlockStrawberryMP". Zawartość tego pliku będzie bardzo podobna. Zmienimy tylko nazwę nasionek które będą wyrzucone i owoców jakie powstaną. Oczywiście zmianie ulegną też tekstury naszej rośliny.

 

BlockStrawberryMP.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.blocks.plants;

import java.util.Random;

import modmevipack.mods.ModItemsMP;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCrops;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;
import net.minecraft.world.World;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class BlockStrawberryMP extends BlockCrops 
{
	@SideOnly(Side.CLIENT)
	public static Icon[] iconArray;
	
	public BlockStrawberryMP(int par1) 
	{
		super(par1);
	}
	
	@Override
	public boolean canBlockStay(World par1World, int par2, int par3, int par4)
	{
		int par5 = par1World.getBlockId(par2, par3 - 1, par4);
		
		return par5 == Block.tilledField.blockID || par5 == Block.grass.blockID || par5 == Block.dirt.blockID;
        }
	
	@Override
	public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7) 
	{	
		ItemStack ret = new ItemStack(idDropped(par5, par1World.rand, par7), quantityDropped(par5, 0, par1World.rand), 0);
		this.dropBlockAsItem_do(par1World, par2, par3, par4, ret);
        }
	
	@Override
	public boolean onBlockActivated(World world, int i, int j, int k, EntityPlayer entity, int l, float m, float n, float o)
	{
		int par1 = world.getBlockMetadata(i, j, k);
		if ( par1 > 6 ) 
		{
			this.dropBlockAsItemWithChance(world, i, j, k, par1, 1.0F, 0);
			world.setBlockMetadataWithNotify(i, j, k, 0, 2);
			return true;
		} 
		else 
		{
			return false;
		}
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public Icon getIcon(int par1, int par2)
	{
		if (par2 > 6) 
		{
			return this.iconArray[2];	
		}
		else if (par2 < 3)
		{
			return this.iconArray[0];
		} 
		else 
		{
			return this.iconArray[1];
		}
	}
	
	@Override
	public int idDropped(int par1, Random par2Random, int par3)
	{
		if (par1 > 6) 
		{
			return getCropItem();
		} 
		else 
		{
			return getSeedItem();
		}
	}
	
	@Override
	public int quantityDropped(int par1, int fortune, Random random) 
	{
		if (par1 > 6 ) 
		{
	    	int i = random.nextInt(3) + 1;
	    	return i;
	    } 
		else 
		{
	    	return 1;
	    }
	}
	
	@Override
	protected int getSeedItem() 
	{
		return ModItemsMP.mPlantSeeds.itemID;
	}
	 
	@Override
	protected int getCropItem() 
	{
		return ModItemsMP.mVegFruStrawberry.itemID;
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void registerIcons(IconRegister par1IconRegister)
	{
		this.iconArray = new Icon[3];
		
		for (int i = 0; i < this.iconArray.length; ++i)
		{
			this.iconArray[i] = par1IconRegister.registerIcon("modmevipack:plants/mStrawberry" + i);
		}
	}
}

Gdy porównacie oba pliki, to zauważycie że są one prawie identyczne.

 

 

2. Główny plik nasionek.

 

Stworzymy teraz główny plik który będzie odpowiadał naszym nasionom. W paczce "modmevipack.items" tworzymy nowy plik class i nazywamy go "ItemPlantSeedsMP"

 

ItemPlantSeedsMp.class

// ModMeviPack - Polska modyfikacja do Minecraft'a by Mevistor
package modmevipack.items;

import java.util.List;

import modmevipack.ModMeviPack;
import modmevipack.mods.ModBlocksMP;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;
import net.minecraft.world.World;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class ItemPlantSeedsMP extends Item
{
	private static final String[] nameseed = new String[] {"Blueberry","Strawberry"};
	
	@SideOnly(Side.CLIENT)
	private Icon[] icons;
	
	public ItemPlantSeedsMP(int par1) 
	{
		super(par1);
		this.setHasSubtypes(true);
		this.setCreativeTab(ModMeviPack.mTabModMeviPack);
	}
	
	public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
	{
		int BlockID;
		if (Block.blocksList[this.CheckID(par1ItemStack.getItemDamage())].canBlockStay(par3World, par4, par5 + 1, par6)) 
		{
			par3World.setBlock(par4, par5 + 1, par6, this.CheckID(par1ItemStack.getItemDamage()));		
			--par1ItemStack.stackSize;
			return true;	
		} 
		else 
		{
			return false;
		}
	}
	
	public int CheckID(int par1)
	{
		switch (par1) 
		{
			case 0 : return ModBlocksMP.mBlueberry.blockID;
			case 1 : return ModBlocksMP.mStrawberry.blockID;
			default : return ModBlocksMP.mBlueberry.blockID;
		}
	}
	
	@Override
	public String getUnlocalizedName(ItemStack par1ItemStack)
	{
		int i = par1ItemStack.getItemDamage();
		return "modmevipack:beds/m" + nameseed[i] + "Seeds";
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void registerIcons(IconRegister par1IconRegister)
	{
		this.icons = new Icon[this.nameseed.length];

		for (int i = 0; i < this.nameseed.length; i++)
		{
			this.icons[i] = par1IconRegister.registerIcon("modmevipack:plants/m" + this.nameseed[i] + "Seeds");
		}
	}
	
	@Override
	public Icon getIconFromDamage(int par1)
	{
		return this.icons[par1];
	}

	@Override
	@SideOnly(Side.CLIENT)
	public void getSubItems(int par1, CreativeTabs par2CreativeTabs, List par3List)
	{
		for (int x = 0; x < this.nameseed.length; x++)
		{
			par3List.add(new ItemStack(this, 1, x));
		}
	}
}

Jest to Item z wartością "meta" przechowywaną w wartości "damage" item'u. Jeden plik (jeden numer id) będzie odpowiadał za kilka nasionek. Już wcześniej o tym pisałem. Tak samo jak w kwiatkach były subBloki, tak tu są subItemy. 

public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
	

Procedura odpowiada za to co się stanie gdy użyjemy nasionka. W tym wypadku będzie ono posadzone (o ile zostaną spełnione warunki). Mamy tu odwołanie do procedury "CheckID" która sprawdza jakie warzywo albo owoc należy zasadzić. Nazwa procedury "CheckID" została wymyślona przezemnie i jest troszkę głupia bo nie ma nic wspólnego ze sprawdzanie ID, tylko "meta". No ale to tylko procedura.

 

Pozostałe funkcje w większości odpowiadają za tekstury (wygląd naszego nasionka)

 

3. "Wykańczanie plantacji"  :crazy: 

 

Teraz stworzymy i zarejestrujemy bloki roślin. Otwieramy klasę "ModBlockMP.java" i dopisujemy takie wartości:

public static final Block mBlueberry = (new BlockBlueberryMP(3200)).setUnlocalizedName("mBlueberry0").setTextureName("modmevipack:plants/mBlueberry0");
public static final Block mStrawberry = (new BlockStrawberryMP(3201)).setUnlocalizedName("mStrawberry0").setTextureName("modmevipack:plants/mStrawberry0");
	

oraz w procedurze "init_BlocksMP()" dopisujemy:

GameRegistry.registerBlock(mBlueberry);
GameRegistry.registerBlock(mStrawberry);

czyli po prostu rejestrujemy bloki.

 

Teraz czas na item'y. Otwieramy plik class "ModItemsMP.class".

Dopisujemy:

public static final Item mPlantSeeds = (new ItemPlantSeedsMP(3280)).setUnlocalizedName("mBlueberrySeeds");
	public static final Item mVegFruBlueberry = (new ItemFood(3300, 1, false)).setCreativeTab(ModMeviPack.mTabModMeviPack).setUnlocalizedName("mVegFruBlueberry").setTextureName("modmevipack:plants/mBlueberry");
	public static final Item mVegFruStrawberry = (new ItemFood(3301, 1, false)).setCreativeTab(ModMeviPack.mTabModMeviPack).setUnlocalizedName("mVegFruStrawberry").setTextureName("modmevipack:plants/mStrawberry");
	

Jak widzicie są to owoce i są one jadalne. Każde z nich da nam pół serduszka życia!

 

Jeszcze tylko zmienne językowe i o to mamy (plik: "LanguageMP.class").

LanguageRegistry.addName(new ItemStack(ModItemsMP.mPlantSeeds, 1, 0), "Sadzonka jagod");
LanguageRegistry.addName(new ItemStack(ModItemsMP.mPlantSeeds, 1, 1), "Sadzonka truskawek");
		
LanguageRegistry.addName(ModItemsMP.mVegFruBlueberry, "Jagody");
LanguageRegistry.addName(ModItemsMP.mVegFruStrawberry, "Truskawka");

Dodamy jeszcze receptury. Z każdego owoca/warzywa będziemy mogli otrzymać sadzonki.

Otwieramy "ModRecipesMP.class" i dopisujemy:

GameRegistry.addRecipe(new ItemStack(ModItemsMP.mPlantSeeds, 1, 0), new Object[] {"A", Character.valueOf('A'), new ItemStack(ModItemsMP.mVegFruBlueberry, 1),});

GameRegistry.addRecipe(new ItemStack(ModItemsMP.mPlantSeeds, 1, 1), new Object[] {"A", Character.valueOf('A'), new ItemStack(ModItemsMP.mVegFruStrawberry, 1),});
		

To by było na tyle. Stworzyliśmy dwie nowe rośliny do uprawy w grze!

Dodam tylko że w kodzie który pisaliśmy w poprzednich częściach wprowadziłem małe kosmetyczne poprawki. Warto przestudiować kod źródłowy, który umieszczam tutaj:

 

Zaloguj lub zarejestruj się aby zobaczyć ten link.

 

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Mevistor    31

Witam!

 

Mała poprawka w stosunku do poprzedniego artykułu. Zrobiłem błąd  :crazy: ! Gdy zniszczymy blok truskawki, zawsze wypadnie z niego sadzonka jagód, ale z właściwą teksturą. Aby ten błąd naprawić musimy wprowadzić w pliku "BlockStrawberryMP.java", w procedurze "dropBlockAsItemWithChance" małą zmiane.

 

Nasz kod wyglądał tak:

@Override
	public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7) 
	{	
		ItemStack ret = new ItemStack(idDropped(par5, par1World.rand, par7), quantityDropped(par5, 0, par1World.rand), par8);
		this.dropBlockAsItem_do(par1World, par2, par3, par4, ret);
    }

Dopisujemy dwie krótkie linijki kodu i teraz wygląda tak:

@Override
	public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7) 
	{	
		int par8;
		
		if (par5 > 6) { par8 = 0; } else { par8 = 1; };
		
		ItemStack ret = new ItemStack(idDropped(par5, par1World.rand, par7), quantityDropped(par5, 0, par1World.rand), par8);
		this.dropBlockAsItem_do(par1World, par2, par3, par4, ret);
    }

W poprzedniej wersji do nasionka był przypisywany zły numer w meta. Co skutkowało tym błędem, oraz tym że owoce wypadające nie dało się Craftować, gdyż miały również zły numer meta.

 

Za błąd przepraszam!  :0

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
TheMystez    4

Bardzo dobry poradnik, dla tych, którzy się w tym orientują i się tym bawią ;D

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Derpson120    0

ja próbuje zainstalować eclipse ale wyskakuje mi błąd , próbowałem instlować różne wersje JDK i eclipse ale nie moge zainstalować  :(

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.

×
×
  • Dodaj nową pozycję...