So, you want to make a block like cloth or conserve your block ids? Well, you've come to the right thread. Here, I shall describe the process of creating such a block.
What you need:
MCP 5.0 for 1.0.*
ModLoader for 1.0.*
Files to create:
We shall call this block "Multifaceted". For this multifaceted block, we will need to create three classes.
mod_Multifaceted - Change to the name of your mod.
ItemMultifaceted
BlockMultifaceted
Some things to keep in mind:
Items have damage values. Blocks have metadata values.
Damage values have to be between 0 and 15, inclusive.
I register blocks and textures in a more manageable way that most tutorial writers. I'll have to write a tutorial on it.
I've rewritten parts of this five times. If something doesn't flow properly, tell me!
And now, what you shall be learning:
Classes needed to make a block with damage values/metadata values.
How to give each damage value its own name.
How to make each damage value show up in TMI with good names.
How to have the texture set by metadata value.
">Mod Class (mod_Multifaceted)
Alright, to start off, we define our mod class.
package net.minecraft.src;
/**
*
* @author YOUR NAME
*
*/
public class mod_Multifaceted extends BaseMod {
// Define property file.
@MLProp(min=133.0D, max=255.0D) public static int MultifacetedBlockId = 129;
// Define texture overrides.
public static int texture1 = ModLoader.addOverride("/terrain.png", "/path/to/texture1.png");
public static int texture2 = ModLoader.addOverride("/terrain.png", "/path/to/texture2.png");
public static int texture3 = ModLoader.addOverride("/terrain.png", "/path/to/texture3.png");
//etc. etc.
public mod_Multifaceted() {
}
@Override
public String getVersion() {
return "r1 for 1.0.*";
}
@Override
public void load(){
Block multifaceted = new BlockMultifaceted(MultifacetedBlockId);
ModLoader.RegisterBlock(multifaceted, net.minecraft.src.ItemMultifaceted.class);
ModLoader.AddName(new ItemStack(multifaceted, 1, 0), "Multifaceted 0");
ModLoader.AddName(new ItemStack(multifaceted, 1, 1), "Multifaceted 1");
ModLoader.AddName(new ItemStack(multifaceted, 1, 2), "Multifaceted 2");
//etc. etc.
//Add Recipes (these recipes won't work -- Empty!)
ModLoader.AddRecipe(new ItemStack(multifaceted, 1, 0), new Object[]{});
ModLoader.AddRecipe(new ItemStack(multifaceted, 1, 1), new Object[]{});
ModLoader.AddRecipe(new ItemStack(multifaceted, 1, 2), new Object[]{});
//ect. ect.
}
}
Alright. This is quite a lot of code, so let us break it down.
The first line is the ever present package line. Then there is an annotation for your name. Use your real name.
Afterwards, we begin the class for the mod. The first think I do is set a property file. Other tutorials explain how it works. It's not required, but it's user friendly.
Right after, are static definitions for textures. Use as many as you need. Declaring your textures as their own variable allows you to be well, more declarative. And declarative programming is much easier to read and modify in the future.
Next is an implementation for the version. This is a required function. These are all standard parts you should have in the mod class file. If you don't understand them, don't ask questions about them here. I'll just direct you to Google.
The first line defines the block. You'll notice that compared to most tutorials, this definition is extremely bare. You only pass it the block id and you don't set any block properties! You'll find these properties can (and are defined) in the blocks class itself.
Then register the block for Block Metadata/Item Damage cohesion using the following version of ''registerBlock''.
Using this version of the registerBlock method tells the code the parts necessary to make crafting, placing, and mining of the block work smoothly.
After defining the block, we add ModLoader names. You see that you pass it an ItemStack of your item. You create a new ItemStack because you get the in-game name of the item from it's damage value in the item class, and you add the name to the damaged version. If you haven't seen this constructor for ItemStack before, here is the signature:
ItemStack(Item item, int quantity, int damage);
After registering your blocks, you probably want to register recipes. Use whatever method you use to create the recipe, but remember to use the constructor shown above.
And with that, you don't have to touch the mod class for modifying this block, unless you are modifying textures. If you really wanted to, you could move the textures to the block class too.
Item Class (ItemMultifaceted)
package net.minecraft.src;
public class ItemMultifaceted extends ItemBlock {
public static String[] blockNames = { "Multifaceted 1 Name", "Multifaceted 2 Name",
"Multifaceted 3 Name" /* ect. ect. */ }
public ItemMultifaceted(int id) {
super(id);
setMaxDamage(0);
setHasSubtypes(true);
}
public int getPlacedBlockMetadata(int damage) {
return damage;
}
public String getItemNameIS(ItemStack itemstack) {
return (new StringBuilder())
.append(super.getItemName())
.append(".")
.append(blockNames[itemstack.getItemDamage()])
.toString();
}
}
The constructor and getPlacedBlockMetadata methods are copy & paste.
ModLoader will call the constructor for you. I'm not sure if setMaxDamage(0) is necessary or not, but without setHasSubtypes(true), damage values get replaced in ItemStack manipulation in the inventory.
I'm not sure how getPlacedBlockMetadata works, so I have no comment on it. I cannot guarantee what will happen if you change this method.
The ''blockNames[]'' String array defines the in-game names of your item. Position n (starting with 0) on the array corresponds to damage value n. The game will crash into a "Saving Chunks" screen if a player picks up a block without one of these names. Adding these names makes these blocks visible from Too Many Items, and this is the name that you will see.
Block Class (BlockMultifaceted)
package net.minecraft.src;
import java.util.Random;
public class BlockMultifaceted extends Block {
public BlockMultifaceted(int id) {
super(id, Material.someMaterial);
this.setHardness(1.0F);
this.setResistance(1F);
this.setStepSound(Block.soundSomeSound);
this.setBlockName("Multifaceted");
}
public int idDropped(int metadata, Random random) {
return blockID;
}
protected int damageDropped(int metadata) {
return metadata;
}
/**
*
* Pick one of the following 3 code blocks.
*
*/
// If you use metadata to change the texture of the block.
public int getBlockTextureFromSideAndMetadata(int side, int metadata) {
switch (metadata){
case 0: return mod_Multifaceted.texture1;
case 1: return mod_Multifaceted.texture2;
case 2: return mod_Multifaceted.texture3;
//etc. etc.
}
}
// If you use the side of the block but not metadata.
public int getBlockTextureFromSide(int side){
switch (side){
case 0: return mod_Multifaceted.texture1;
case 1: return mod_Multifaceted.texture2;
case 2: return mod_Multifaceted.texture3;
//etc. etc.
}
}
// If you only use one texture at all.
this.blockIndexInTexture = mod_Multifaceted.texture1;
// If you choose this one, you can put it with all the other this.* declarations.
}
As you can see, special properties, like the block name, step sound, resistance, and hardness are all defined here in the block. The "this." isn't needed, strictly speaking, but I think it helps the readability. These properties really should be defined inside the block, since these properties are logically about the block, and not logically, about the mod. But enough of my tangent, on to the rest of the code.
The idDropped method is unchanged, but there is a new method called damageDropped. It is passed one integer, the metadata value of the block. This function is called when you break it, and the item of the block will have the damage as specified by the return value.
And then you see that you have three blocks to choose from. These are where your texture(s) get defined at. The bottom two are hopefully familiar, and you can look at Block.Cloth for another example of different textures based on metadata.
??? to hard for me just upload the file and make a download link
I don't actually have a file to upload. This is an abstraction of code I fiddled with to get separate functionality out of the same block. It's a tutorial you cannot just copy and paste without understanding at least a little bit what you are doing.
OK, I got everything to work perfectly. I made a multiplayer version (Using BaseModMp instead of BaseMod and removing ModLoader.AddName serverside), but when I place a block in multiplayer that has metadata of anything but 0, It aoutomatically reverts to 0.
Example: I craft 3 of Multifaceted, metadata 3 on the server.
It looks like the actual #3 in the inventory, but the moment I place it in the world, it turns into the block that is Multifaceted-0.
Ahem... well If I am not mistaken you have to many variables for your block-
world.setBlockMetadataWithNotify(i, j, k, l);
4 integer values whereas you have 5-
The name should be stored in the block file and then set to each metadata value
Ahem... well If I am not mistaken you have to many variables for your block-
world.setBlockMetadataWithNotify(i, j, k, l);
4 integer values whereas you have 5-
The name should be stored in the block file and then set to each metadata value
Oh thanks! Do you know how exactly I would write that if it is
Nevermind, we were both wrong. It WAS 5 variables, but mod_Spano.FlowerCap.blockID had to be 130 [the id of the block] Thanks anyway tho, i generated my giant yellow flower! now tomorrow, red flower
Nevermind, we were both wrong. It WAS 5 variables, but mod_Spano.FlowerCap.blockID had to be 130 [the id of the block] Thanks anyway tho, i generated my giant yellow flower! now tomorrow, red flower
Oh yeah i see what I did there haha i pulled up a block that was already registered so it wouldnt have called for the id just the xyz and meta- haha fale on my part
I have updated this for 1.0.*. Not sure if it is fully upgraded, but I'm pretty sure the only change is to move the code that was in the constructor to the load() method and to rename version to getVersion().
Idk what I'm doing wrong. For some reason I keep getting NullPointers to the addName function.
I'm using the forge API but as far as I know that should not be the problem?
Error:
Caused by: java.lang.NullPointerException
at net.minecraft.src.ModLoader.AddName(ModLoader.java:304)
at net.minecraft.src.mod_SMPEP.load(mod_SMPEP.java:65)
at net.minecraft.src.ModLoader.init(ModLoader.java:739)
... 6 more
Code:
public void load()
{
//Init Items and Blocks.
Item itemCoin = new ItemCoin(itemCoinID - 256);
Block blockSMPEPOres = new BlockSMPEPOres(blockSMPEPOresID, 0);
//Register Blocks.
[b]ModLoader.RegisterBlock(blockSMPEPOres, net.minecraft.src.BlockSMPEPOres.class[/b]);
//Add Names.
ModLoader.AddName(new ItemStack(blockSMPEPOres, 1, 0), "Copper Ore");
ModLoader.AddName(new ItemStack(blockSMPEPOres, 1, 1), "Tin Ore");
ModLoader.AddName(new ItemStack(blockSMPEPOres, 1, 2), "Silver Ore");
ModLoader.AddName(new ItemStack(blockSMPEPOres, 1, 3), "Mithril Ore");
//Preload all texture files so they show up correctly.
MinecraftForgeClient.preloadTexture("/rimevel/SMPEP/blocks.png");
MinecraftForgeClient.preloadTexture("/rimevel/SMPEP/new_items.png");
}
}
I'm quite new to this so I'm sure it's some newbie mistake
I bolded the line that looks like it has the probable error. The second parameter to ModLoader.RegisterBlock() must be a class for an Item. You have it pointing at the block.
(If that isn't it, can you point out which line 65 is in your code?)
Andor: I cannot see anything about metadata in that code...
Golui: You probably can by querying for the metadata of the block and doing logic off of it. Metadata is really just a 4 bit extension to the 8 bits that make up the block ID.
can someone tell me this:
when i place my multi-textured block how do i make so that the front of the block faces me when i place it.
anyone?
/**
* Assumption: Metadata is set when block is placed so that 0-4
* correlate with North->West in clockwise direction.
*
* How this metadata is set, I'm not sure.
*/
public int getBlockTextureFromSideAndMetadata(int side, int metadata) {
switch (metadata) {
case 0: // Player placed block North of him.
switch (side) {
case 0: return mod_Multifaceted.topTexture;
case 1: return mod_Multifaceted.bottomTexture;
case 2: return mod_Multifaceted.rightTexture;
case 3: return mod_Multifaceted.leftTexture;
case 4: return mod_Multifaceted.frontTexture;
case 5: return mod_Multifaceted.backTexture;
default: return null;
}
case 1: // Player placed block East of him
switch (side) {
case 0: return mod_Multifaceted.topTexture;
case 1: return mod_Multifaceted.bottomTexture;
case 2: return mod_Multifaceted.backTexture;
case 3: return mod_Multifaceted.frontTexture;
case 4: return mod_Multifaceted.leftTexture;
case 5: return mod_Multifaceted.rightTexture;
default: return null;
}
case 2: // Player placed block South of him
switch (side) {
case 0: return mod_Multifaceted.topTexture;
case 1: return mod_Multifaceted.bottomTexture;
case 2: return mod_Multifaceted.leftTexture;
case 3: return mod_Multifaceted.rightTexture;
case 4: return mod_Multifaceted.backTexture;
case 5: return mod_Multifaceted.frontTexture;
default: return null;
}
case 3: // Player placed block West of him
switch (side) {
case 0: return mod_Multifaceted.topTexture;
case 1: return mod_Multifaceted.bottomTexture;
case 2: return mod_Multifaceted.frontTexture;
case 3: return mod_Multifaceted.backTexture;
case 4: return mod_Multifaceted.rightTexture;
case 5: return mod_Multifaceted.leftTexture;
default: return null;
}
}
}
I'd have to dig through the code to figure out how to determine which direction the player is placing it, but once that is known, it's simply setting the metadata.
ok i made my code but i get an error (i'm using eclipse) on the bit that says "default: return null;" the null is underlined in red. I have no idea how to fix this because i'm really bad with metadata and such...
this is my mod_*.java code (not all of it just the bits you need to look at):
java.lang.Error: Unresolved compilation problems:
Type mismatch: cannot convert from null to int
Type mismatch: cannot convert from null to int
Type mismatch: cannot convert from null to int
Type mismatch: cannot convert from null to int
at net.minecraft.src.BlockGingerbreadHouse.getBlockTextureFromSideAndMetadata(BlockGingerbreadHouse.java:25)
at net.minecraft.src.Block.getBlockTexture(Block.java:361)
at net.minecraft.src.RenderBlocks.renderStandardBlockWithAmbientOcclusion(RenderBlocks.java:3208)
at net.minecraft.src.RenderBlocks.renderStandardBlock(RenderBlocks.java:2938)
at net.minecraft.src.RenderBlocks.renderBlockByRenderType(RenderBlocks.java:225)
at net.minecraft.src.WorldRenderer.updateRenderer(WorldRenderer.java:187)
at net.minecraft.src.RenderGlobal.updateRenderers(RenderGlobal.java:1246)
at net.minecraft.src.EntityRenderer.renderWorld(EntityRenderer.java:887)
at net.minecraft.src.EntityRenderer.updateCameraAndRender(EntityRenderer.java:747)
at net.minecraft.src.EntityRendererProxy.updateCameraAndRender(EntityRendererProxy.java:25)
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:729)
at net.minecraft.client.Minecraft.run(Minecraft.java:627)
at java.lang.Thread.run(Unknown Source)
--- END ERROR REPORT 1740128c ----------
hope you could help me out...
thnx
Dang. I thought Java would allow null there. Use 0 or any other int value instead. The code should never make it to the value in any case.
I have a problem. I have it working, but a few bugs. First of all, I can't place the metadata blocks. Also, there are other metadatas created, I want 140, 140:1, and 140:2. Not 140:6, and 140:8 ect.
What you need:
Files to create:
We shall call this block "Multifaceted". For this multifaceted block, we will need to create three classes.
Some things to keep in mind:
And now, what you shall be learning:
">Mod Class (mod_Multifaceted)
Alright, to start off, we define our mod class.
Alright. This is quite a lot of code, so let us break it down.
The first line is the ever present package line. Then there is an annotation for your name. Use your real name.
Afterwards, we begin the class for the mod. The first think I do is set a property file. Other tutorials explain how it works. It's not required, but it's user friendly.
Right after, are static definitions for textures. Use as many as you need. Declaring your textures as their own variable allows you to be well, more declarative. And declarative programming is much easier to read and modify in the future.
Next is an implementation for the version. This is a required function. These are all standard parts you should have in the mod class file. If you don't understand them, don't ask questions about them here. I'll just direct you to Google.
The first line defines the block. You'll notice that compared to most tutorials, this definition is extremely bare. You only pass it the block id and you don't set any block properties! You'll find these properties can (and are defined) in the blocks class itself.
Then register the block for Block Metadata/Item Damage cohesion using the following version of ''registerBlock''.
Using this version of the registerBlock method tells the code the parts necessary to make crafting, placing, and mining of the block work smoothly.
After defining the block, we add ModLoader names. You see that you pass it an ItemStack of your item. You create a new ItemStack because you get the in-game name of the item from it's damage value in the item class, and you add the name to the damaged version. If you haven't seen this constructor for ItemStack before, here is the signature:
After registering your blocks, you probably want to register recipes. Use whatever method you use to create the recipe, but remember to use the constructor shown above.
And with that, you don't have to touch the mod class for modifying this block, unless you are modifying textures. If you really wanted to, you could move the textures to the block class too.
Item Class (ItemMultifaceted)
The constructor and getPlacedBlockMetadata methods are copy & paste.
ModLoader will call the constructor for you. I'm not sure if setMaxDamage(0) is necessary or not, but without setHasSubtypes(true), damage values get replaced in ItemStack manipulation in the inventory.
I'm not sure how getPlacedBlockMetadata works, so I have no comment on it. I cannot guarantee what will happen if you change this method.
The ''blockNames[]'' String array defines the in-game names of your item. Position n (starting with 0) on the array corresponds to damage value n. The game will crash into a "Saving Chunks" screen if a player picks up a block without one of these names. Adding these names makes these blocks visible from Too Many Items, and this is the name that you will see.
Block Class (BlockMultifaceted)
As you can see, special properties, like the block name, step sound, resistance, and hardness are all defined here in the block. The "this." isn't needed, strictly speaking, but I think it helps the readability. These properties really should be defined inside the block, since these properties are logically about the block, and not logically, about the mod. But enough of my tangent, on to the rest of the code.
The idDropped method is unchanged, but there is a new method called damageDropped. It is passed one integer, the metadata value of the block. This function is called when you break it, and the item of the block will have the damage as specified by the return value.
And then you see that you have three blocks to choose from. These are where your texture(s) get defined at. The bottom two are hopefully familiar, and you can look at Block.Cloth for another example of different textures based on metadata.
I don't actually have a file to upload. This is an abstraction of code I fiddled with to get separate functionality out of the same block. It's a tutorial you cannot just copy and paste without understanding at least a little bit what you are doing.
Although, I am having trouble with the textures. I am trying to use textures that are already in the default terrain.png file, and I've tried to
but I still get a textureless block. Any suggestions?
My only thought would be to make sure there is actually a texture at 64. Otherwise, I am not sure. :/
Yeah, It's white wool, but whenever I place my block, the texture is the one in place of 0.
Must be that I'm telling it to change the texture in the wrong way, making it into the default...
Example: I craft 3 of Multifaceted, metadata 3 on the server.
It looks like the actual #3 in the inventory, but the moment I place it in the world, it turns into the block that is Multifaceted-0.
Any suggestions?
[code]
src\minecraft\net\minecraft\src\ItemFertilizer.java:99: cannot find symbol
symbol : variable FlowerCap
location: class net.minecraft.src.mod_Nature
world.setBlockAndMetadataWithNotify(i, j, k, mod_Nature.FlowerCap.blockID, 3);
^
14 errors
==============
What I mainly want to know is where the name of the FlowerCap is. Any details help, also
Ahem... well If I am not mistaken you have to many variables for your block-
world.setBlockMetadataWithNotify(i, j, k, l);
4 integer values whereas you have 5-
The name should be stored in the block file and then set to each metadata value
Oh thanks! Do you know how exactly I would write that if it is
like that? Thanks
**EDIT**
Nevermind, we were both wrong. It WAS 5 variables, but mod_Spano.FlowerCap.blockID had to be 130 [the id of the block] Thanks anyway tho, i generated my giant yellow flower! now tomorrow, red flower
Oh yeah i see what I did there haha i pulled up a block that was already registered so it wouldnt have called for the id just the xyz and meta- haha fale on my part
See Rigusami's decompile fix.
I bolded the line that looks like it has the probable error. The second parameter to ModLoader.RegisterBlock() must be a class for an Item. You have it pointing at the block.
(If that isn't it, can you point out which line 65 is in your code?)
Golui: You probably can by querying for the metadata of the block and doing logic off of it. Metadata is really just a 4 bit extension to the 8 bits that make up the block ID.
I'd have to dig through the code to figure out how to determine which direction the player is placing it, but once that is known, it's simply setting the metadata.
Dang. I thought Java would allow null there. Use 0 or any other int value instead. The code should never make it to the value in any case.
https://assortedmods.com/