These tutorials are for the people who have mastered the simple stage of modding. In the future, it will include creating an API to allow other modders to create addons for your mod, and also integrate it in their mod as well. It will also teach you tanks and liquids, and multiblock structures.
I recommend you at least know how to: 1) Know how to use world gen 2) Basic Modding skillswith forge 3) High Java Knowledge 4) Tile entities 5) Tick handlers and Gui Handlers 6) Know how to read error logs, unless it's a null pointer exception before attempting any of these tutorials.
Also, not all tutorials are complete yet.
TL;DR: Don't screw around with these tutorials and bring me error logs you aren't reading, or don't know how to read. Don't come here if you only have a mod with just items, because that doesn't do much. It's called advanced modding for a reason.
Error Logs:
Bring them to me in PM, not on the thread. One of my biggest annoyances is error logs that are not properly formatted into a thread. So, for my convenience, please PM me your error logs.
Now let's get into the coding, shall we?
Modular Item System
A modular item system is an item that you can add modules to. The modular powersuit addon is a great example of modular items/armor, and that's exactly what we're making in this tutorial.
The code:
package advancedmodding.modularitem;
import java.util.Map;
import java.util.HashMap;
import net.minecraft.item.Item;
public class ItemModularTool extends Item
{
public static final Block[] pickaxeBlocksEffectedAgainst = new Block[] {Block.cobblestone, Block.stoneDoubleSlab, Block.stoneSingleSlab, Block.stone, Block.sandStone, Block.cobblestoneMossy, Block.oreIron, Block.blockSteel, Block.oreCoal, Block.blockGold, Block.oreGold, Block.oreDiamond, Block.blockDiamond, Block.ice, Block.netherrack, Block.oreLapis, Block.blockLapis, Block.oreRedstone, Block.oreRedstoneGlowing, Block.rail, Block.railDetector, Block.railPowered, Block.field_94337_cv};
public ItemModularTool(int i)
{
super(i);
}
private static Map installedModuleList = new HashMap();
public static void addModule(String module, int function)
{
if(!installedModuleList.containsKey(module))
{
installedModuleList.put(module, function);
}
}
@Override
public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5)
{
super.onUpdate(par1ItemStack, par2World, par3Entity, par4, par5);
if(installedModuleList.containsKey("anymodulename"))
{
int i = installedModuleList.get("anymodulename");
this.moduleFunction(i);
}
}
public void moduleFunction(int i)
{
switch(i)
{
case 0:
this.damageVsEntity(10);
case 1:
this.blockEffectiveAgainst = this.pickaxeBlocksEffectiveAgainst;
}
}
}
So now let's look at the code:
private static Map installedModuleList = new HashMap();
This code creates a java list of modules this item has installed. It's not much more than a regular HashMap, so let's continue.
public static void addModule(String module, int function)
{
if(!installedModuleList.containsKey(module))
{
installedModuleList.put(module, function);
}
}
Now this code adds a module into the HashMap. The first argument (String module) is the name of the module. In this case, one of them could be named "Sharp Point." The second argument (int function) is an integer that determines the function, which is handled later. In the case for "Sharp Point," the integer is 0.
@Override
public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5)
{
super.onUpdate(par1ItemStack, par2World, par3Entity, par4, par5);
if(installedModuleList.containsKey("anymodulename"))
{
int i = installedModuleList.get("anymodulename");
this.moduleFunction(i);
}
}
This method is called every tick the item is on the player's inventory. It sees if the item has the module "anymodulename" installed. If you have multiple modules, you must repeat this "if" statement for all the module names you have. We will handle API module entries when we get there. You can replace "anymodulename" with a module you have created. If it's installed into the module, it gets the function integer and calls the "moduleFunction" method with it's required argument.
public void moduleFunction(int i)
{
switch(i)
{
case 0:
this.damageVsEntity(10);
case 1:
this.blockEffectiveAgainst = this.pickaxeBlocksEffectiveAgainst;
}
}
The final method, the moduleFunction(int i) method. This method takes a module function and interprets it into the item. Earlier, I used the example of the "Sharp Point" module. It had a function integer of 0. If it gets run into the function class, it then causes the item to do 10 hit points of damage on any entity it hits.
Block battery that retains it's capacity when picked up
Block Class
package tutorial;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class BlockBattery extends Block
{
public int blockDataValue;
public BlockBattery(int i, Material m)
{
super(i, m);
}
@Override
public void onBlockAdded(World world, int i, int j, int k)
{
this.blockDataValue = ItemBlockBattery.value;
}
public int idDropped(int par1, Random par2Random, int par3)
{
ItemStack stack = new ItemStack(ModClass.ItemBlockBattery.itemID, 1, this.blockDataValue/200);
return stack.itemID;
}
@Override
public int quantityDropped(Random random)
{
return 1;
}
}
Item Block Class
package tutorial;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class ItemBlockBattery extends ItemBlock
{
public static int value;
public ItemBlockBattery(int i)
{
super(i);
this.setMaxDamage(30);
this.setMaxStackSize(1);
ItemStack stack = new ItemStack(this);
this.value = stack.getItemDamage()*200;
}
}
Now let's explain the code.
The ItemBlock class is the block while it's in the inventory. We need one in order to show the power level while your holding it. The ItemBlock class itself takes care of most of the work.
Now in the block class, it's very simple. It's told to drop one ItemBlock with a value of it's energy stored divided by 200 (so it fits the damage bar ). When it's placed it takes the value from the ItemBlock and sets it as it's own.
Just wondering here, wouldn't " this.blockDataValue" be the exactly the same for every block inn the game, since minecraft only have one instance of the block?
Just wondering here, wouldn't " this.blockDataValue" be the exactly the same for every block inn the game, since minecraft only have one instance of the block?
The method is called for that specific instance of the block class, each separate class has it's own energy value.
The method is called for that specific instance of the block class, each separate class has it's own energy value.
But doesn't minecraft just keep 1 instance of every block class at any given time?
I'm sure that what you write works, but I don't understand why since I was under the impression that blocks where stored by their blockID and from that related to their one and only instance to execute general methods?
But doesn't minecraft just keep 1 instance of every block class at any given time?
I'm sure that what you write works, but I don't understand why since I was under the impression that blocks where stored by their blockID and from that related to their one and only instance to execute general methods?
Every separate block in the world has it's own instance.
How can they be, as they are static?
Looking at the Block class, line 96 for example:
public static final Block stone = (new BlockStone(1)).
World's setBlock leads into Chunk's setBlockIDWithMetadata.
This in turn ends up using Extendedblockstorage's setExtBlockID method.
Inside it would seem to me that it splits the bit's for the blockID into two arrays (blockMSBArray and BlockLSBArray)
So to me it would seem that all blocks are stored as into, or rather pices of an int inside NibbleArray's
as both the setBlock and getBlock leads to these arrays?
That is with world saving. Upon world load they load separate instances with separate NBTs.
What you probably mean are TileEntities. They are unique and for every block there's an instance for it, as long as the block has a TileEntity specified. Blocks itself have only ONE instance. Blocks in the world data, as long as they don't have an TE, are only saved as BlockID / Metadata combination value made out of 16 bits: The Block ID takes 12 bits whereas the metadata takes 4.
If every block on the world has its own instance it would be a massive performance hit, since every instance needs to be saved in the memory, and blocks wouldn't need TileEntities for saving extended data (like inventories).
What you probably mean are TileEntities. They are unique and for every block there's an instance for it, as long as the block has a TileEntity specified. Blocks itself have only ONE instance. Blocks in the world data, as long as they don't have an TE, are only saved as BlockID / Metadata combination value made out of 16 bits: The Block ID takes 12 bits whereas the metadata takes 4.
If every block on the world has its own instance it would be a massive performance hit, since every instance needs to be saved in the memory, and blocks wouldn't need TileEntities for saving extended data (like inventories).
It shouldn't. The block class for redstone uses similar methods to what I have. It doesn't have a tile, and if it had only 1 instance all redstone in the world would light when 1 does.
It shouldn't. The block class for redstone uses similar methods to what I have. It doesn't have a tile, and if it had only 1 instance all redstone in the world would light when 1 does.
Redstone blocks use metadata to store unique values, which other blocks do as well. Metadata is stored separately for each block in the world save file, but block ID is static and never changes, as Mazetar pointed out. If you're referring to the 'active' and 'idle' state of certain redstone blocks, if you look further you'll find that each one of those is actually a separate block with its own unique ID. (I'm pretty late to the party - found myself here after searching for multiblock tutorials :P)
I recommend you at least know how to:
1) Know how to use world gen
2) Basic Modding skills with forge
3) High Java Knowledge
4) Tile entities
5) Tick handlers and Gui Handlers
6) Know how to read error logs, unless it's a null pointer exception
before attempting any of these tutorials.
Also, not all tutorials are complete yet.
TL;DR: Don't screw around with these tutorials and bring me error logs you aren't reading, or don't know how to read. Don't come here if you only have a mod with just items, because that doesn't do much. It's called advanced modding for a reason.
Error Logs:
Bring them to me in PM, not on the thread. One of my biggest annoyances is error logs that are not properly formatted into a thread. So, for my convenience, please PM me your error logs.
Now let's get into the coding, shall we?
Modular Item System
A modular item system is an item that you can add modules to. The modular powersuit addon is a great example of modular items/armor, and that's exactly what we're making in this tutorial.
The code:
So now let's look at the code:
This code creates a java list of modules this item has installed. It's not much more than a regular HashMap, so let's continue.
Now this code adds a module into the HashMap. The first argument (String module) is the name of the module. In this case, one of them could be named "Sharp Point." The second argument (int function) is an integer that determines the function, which is handled later. In the case for "Sharp Point," the integer is 0.
This method is called every tick the item is on the player's inventory. It sees if the item has the module "anymodulename" installed. If you have multiple modules, you must repeat this "if" statement for all the module names you have. We will handle API module entries when we get there. You can replace "anymodulename" with a module you have created. If it's installed into the module, it gets the function integer and calls the "moduleFunction" method with it's required argument.
The final method, the moduleFunction(int i) method. This method takes a module function and interprets it into the item. Earlier, I used the example of the "Sharp Point" module. It had a function integer of 0. If it gets run into the function class, it then causes the item to do 10 hit points of damage on any entity it hits.
Block battery that retains it's capacity when picked up
Block Class
Item Block Class
Now let's explain the code.
The ItemBlock class is the block while it's in the inventory. We need one in order to show the power level while your holding it. The ItemBlock class itself takes care of most of the work.
Now in the block class, it's very simple. It's told to drop one ItemBlock with a value of it's energy stored divided by 200 (so it fits the damage bar ). When it's placed it takes the value from the ItemBlock and sets it as it's own.
API
Not yet complete!
Click Here to view my WIP Mod!
Currently developing a Tech/Space mod. PM if you can/want to help!
I can do liquids right now, it's quite simple.
Hmm, got to work on that, but I can try to get it up eventually.
Click Here to view my WIP Mod!
Currently developing a Tech/Space mod. PM if you can/want to help!
Just wondering here, wouldn't " this.blockDataValue" be the exactly the same for every block inn the game, since minecraft only have one instance of the block?
The method is called for that specific instance of the block class, each separate class has it's own energy value.
Click Here to view my WIP Mod!
Currently developing a Tech/Space mod. PM if you can/want to help!
Sweet! i look forward to using it!
I don't really need to, MCForge hasn't changed too much.
Click Here to view my WIP Mod!
Currently developing a Tech/Space mod. PM if you can/want to help!
But doesn't minecraft just keep 1 instance of every block class at any given time?
I'm sure that what you write works, but I don't understand why since I was under the impression that blocks where stored by their blockID and from that related to their one and only instance to execute general methods?
It's too easy for a tutorial. Just add:
or something like that to the entity class.
Every separate block in the world has it's own instance.
Click Here to view my WIP Mod!
Currently developing a Tech/Space mod. PM if you can/want to help!
Isn't it because they are all ints used to refer to the one block instance that we need metadata or even TEs?
That is with world saving. Upon world load they load separate instances with separate NBTs.
Click Here to view my WIP Mod!
Currently developing a Tech/Space mod. PM if you can/want to help!
Looking at the Block class, line 96 for example:
World's setBlock leads into Chunk's setBlockIDWithMetadata.
This in turn ends up using Extendedblockstorage's setExtBlockID method.
Inside it would seem to me that it splits the bit's for the blockID into two arrays (blockMSBArray and BlockLSBArray)
So to me it would seem that all blocks are stored as into, or rather pices of an int inside NibbleArray's
as both the setBlock and getBlock leads to these arrays?
What you probably mean are TileEntities. They are unique and for every block there's an instance for it, as long as the block has a TileEntity specified. Blocks itself have only ONE instance. Blocks in the world data, as long as they don't have an TE, are only saved as BlockID / Metadata combination value made out of 16 bits: The Block ID takes 12 bits whereas the metadata takes 4.
If every block on the world has its own instance it would be a massive performance hit, since every instance needs to be saved in the memory, and blocks wouldn't need TileEntities for saving extended data (like inventories).
It shouldn't. The block class for redstone uses similar methods to what I have. It doesn't have a tile, and if it had only 1 instance all redstone in the world would light when 1 does.
Click Here to view my WIP Mod!
Currently developing a Tech/Space mod. PM if you can/want to help!
Redstone blocks use metadata to store unique values, which other blocks do as well. Metadata is stored separately for each block in the world save file, but block ID is static and never changes, as Mazetar pointed out. If you're referring to the 'active' and 'idle' state of certain redstone blocks, if you look further you'll find that each one of those is actually a separate block with its own unique ID. (I'm pretty late to the party - found myself here after searching for multiblock tutorials :P)
If you are looking for multiblock tutorials, check out Minalien.com he has a good one
Also thanks for explaining the issue
Yeah, that's why I said I was late to the party Thanks for the tip, btw. The tutorial on the Forge wiki isn't bad either.