I've been trying to make a custom log block. The block renders fine in hand, but causes a crash when placed. I've tried copying the relevant data directly from the vanilla logs .json to no avail. I'm very new to modding, so I suspect it's some simple thing I keep missing. However, I've seen some similar problems on the minecraft forge forums, although they didn't seem to directly answer my issue. Any help is welcome. Thank you for your time.
MainClass:
package net.mythadventure.mod;
@Mod(modid="mythadventure", name="Myth Adventure", version="Alpha_1.0", dependencies="required-after:FML")
public class MythAdventure
{
public static final String MODID = "mythadventure";
public static final String MODNAME = "Myth Adventure";
public static final String VERSION = "Alpha_1.0";
@Instance(value = MODID)
public static MythAdventure instance;
@SidedProxy(modId="mythadventure", clientSide="net.mythadventure.mod.ClientProxy", serverSide="net.mythadventure.mod.ServerProxy")
public static CommonProxy proxy;
public static CustomLog appleLog;
@EventHandler
public void preInit(FMLPreInitializationEvent e)
{
proxy.preInit(e);
}
@EventHandler
public void init(FMLInitializationEvent e)
{
proxy.init(e);
}
@EventHandler
public void postInit(FMLPostInitializationEvent e)
{
proxy.postInit(e);
}
}
CommonProxy:
package net.mythadventure.mod;
public class CommonProxy
{
public void preInit(FMLPreInitializationEvent e) {}
public void init(FMLInitializationEvent e)
{
MythAdventure.appleLog = new CustomLog(Material.wood, "apple_log", 2.0F, 3.25F, MythAdventure.mythadventureTab);
}
public void postInit(FMLPostInitializationEvent e) {}
}
ClientProxy:
package net.mythadventure.mod;
public class ClientProxy extends CommonProxy
{
@Override
public void preInit(FMLPreInitializationEvent e)
{
super.preInit(e);
}
@Override
public void init(FMLInitializationEvent e)
{
super.init(e);
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#normal not found
and this crash:
Cannot set property PropertyEnum{name=axis, clazz=class net.minecraft.block.BlockLog$EnumAxis, values=[x, y, z, none]} as it does not exist in BlockState{block=mythadventure:apple_log, properties=[]}
To fix the crash, you need to override Block#createBlockState to return a new instance of BlockState with the BlockLog.LOG_AXIS property and your variant property like BlockOldLog and BlockNewLog do.
This may or may not fix the error in the console.
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
To fix the crash, you need to override Block#createBlockState to return a new instance of BlockState with the BlockLog.LOG_AXIS property and your variant property like BlockOldLog and BlockNewLog do.
This may or may not fix the error in the console.
Here is the CustomLog class now:
package net.mythadventure.mod.blocks;
public class CustomLog extends BlockLog {
public static final PropertyEnum VARIANT = PropertyEnum.create("variant", BlockPlanks.EnumType.class, new Predicate() {
public boolean apply(BlockPlanks.EnumType type) {
return type.getMetadata() >= 4;
}
public boolean apply(Object p_apply_1_) {
public int getMetaFromState(IBlockState state)
{
byte b0 = 0;
int i = b0 | ((BlockPlanks.EnumType)state.getValue(VARIANT)).getMetadata() - 4;
switch (CustomLog.SwitchEnumAxis.AXIS_LOOKUP[((BlockLog.EnumAxis)state.getValue(LOG_AXIS)).ordinal()])
{
case 1:
i |= 4;
break;
case 2:
i |= 8;
break;
case 3:
i |= 12;
}
return i;
}
public int damageDropped(IBlockState state)
{
return ((BlockPlanks.EnumType)state.getValue(VARIANT)).getMetadata() - 4;
}
static final class SwitchEnumAxis
{
static final int[] AXIS_LOOKUP = new int[BlockLog.EnumAxis.values().length];
public void setDrops(Item drops)
{
this.dropsOnHarvest = drops;
}
public void setDrops(Block drops)
{
this.dropsOnHarvest = Item.getItemFromBlock(drops);
}
public Item getItemDropped(IBlockState state, Random rand, int fortune)
{
return this.dropsOnHarvest;
}
}
That fixed the crash, but now the error is:
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=x,variant=dark_oak not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=y,variant=dark_oak not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=x,variant=acacia not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=none,variant=acacia not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=z,variant=acacia not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=z,variant=dark_oak not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=y,variant=acacia not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=none,variant=dark_oak not found
The block looks fine in hand still, but has the standard "missing texture" texture.
You should create your own enum with the appropriate values for the variant property. At the moment it's complaining because you haven't defined the model to use for the vanilla variant values.
If you want to use the blockstates file with the variant's name (e.g. apple_log.json > axis=x instead of log.json > variant=apple,axis=x), you'll need to register a custom IStateMapper like vanilla logs do in BlockModelShapes#registerAllBlocks. You should do this with Forge's ModelLoader.setCustomStateMapper method instead of vanilla's BlockModelShapes#registerBlockWithStateMapper method.
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
You should create your own enum with the appropriate values for the variant property. At the moment it's complaining because you haven't defined the model to use for the vanilla variant values.
Okay, thanks so much for your help. I don't know much about coding, I've only been trying to learn it for the past few weeks. I am a disabled Army Intelligence veteran though, and I'm trying really hard to figure this stuff out. I appreciate you giving me a place to work from on fixing this.
Do you know Java? You'll need to know it reasonably well to understand the vanilla code and make a mod.
Slightly related: You should add the @Override annotation to any override methods so the compiler ensures that they do actually override a method in a super class. If a method with @Override doesn't match any super method, you'll get a compiler error telling you.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Do you know Java? You'll need to know it reasonably well to understand the vanilla code and make a mod.
No. Though I do have a lot of time on my hands and I'm pretty good at figuring things out. Do you think I'd be better off starting with a Java for Dummies book or something?
No. Though I do have a lot of time on my hands and I'm pretty good at figuring things out. Do you think I'd be better off starting with a Java for Dummies book or something?
I would highly recommend learning Java before trying to learn Minecraft/Forge.
Books are one option for this, there are also lots of online resources such as TheNewBoston's videos and Vswe's summer course lecture videos (covering both Java and Forge).
I personally learned Java at university after teaching myself basic programming concepts by learning Lua (for World of Warcraft AddOns, which are a lot more limited in scope than Minecraft mods), so I'm not sure how effective these videos are.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
I would highly recommend learning Java before trying to learn Minecraft/Forge.
Books are one option for this, there are also lots of online resources such as TheNewBoston's videos and Vswe's summer course lecture videos (covering both Java and Forge).
I personally learned Java at university after teaching myself basic programming concepts by learning Lua (for World of Warcraft AddOns, which are a lot more limited in scope than Minecraft mods), so I'm not sure how effective these videos are.
Thanks for the links and advice. I think I'll supplement my efforts at learning it as I go by reading a Java for Dummies ebook. I'll also be sure to check out those links.
I've gotten up to Chapter 6 of the Java for Dummies book. Still having learned only the very, very basics so far. I took another swing at the code for log types, using vanilla OldLogs and NewLogs for reference. I feel like I'm getting close to cracking it. I have the logs rendering when I place them, but the three types I have all use the texture for the first type "APPLE" and the block has missing texture in hand. It's also called "null" in inventory. Although when I use F3 it shows up as a log block with "variant:apple".
MainClass:
package net.mythadventure.mod;
@Mod(modid="mythadventure", name="Myth Adventure", version="Alpha_1.0", dependencies="required-after:FML")
public class MythAdventure
{
public static final String MODID = "mythadventure";
public static final String MODNAME = "Myth Adventure";
public static final String VERSION = "Alpha_1.0";
@Instance(value = MODID)
public static MythAdventure instance;
@SidedProxy(modId="mythadventure", clientSide="net.mythadventure.mod.ClientProxy", serverSide="net.mythadventure.mod.ServerProxy")
public static CommonProxy proxy;
public static CustomLog Myth_Log;
@EventHandler
public void preInit(FMLPreInitializationEvent e)
{
proxy.preInit(e);
}
@EventHandler
public void init(FMLInitializationEvent e)
{
proxy.init(e);
}
@EventHandler
public void postInit(FMLPostInitializationEvent e)
{
proxy.postInit(e);
}
}
CommonProxy:
package net.mythadventure.mod;
public class CommonProxy
{
public void preInit(FMLPreInitializationEvent e) {}
public void init(FMLInitializationEvent e)
{
MythAdventure.Myth_Log = (CustomLog) new CustomLog("log").setCreativeTab(MythAdventure.mythadventureTab);
}
public void postInit(FMLPostInitializationEvent e) {}
}
ClientProxy:
package net.mythadventure.mod;
public class ClientProxy extends CommonProxy
{
@Override
public void preInit(FMLPreInitializationEvent e)
{
super.preInit(e);
}
@Override
public void init(FMLInitializationEvent e)
{
super.init(e);
MythAdventure.Myth_Log.RegisterRenderer("log");
}
@Override
public void postInit(FMLPostInitializationEvent e)
{
super.postInit(e);
}
}
CustomLog:
package net.mythadventure.mod.blocks;
public class CustomLog extends BlockLog {
public static final PropertyEnum VARIANT = PropertyEnum.create("variant", CustomPlanks.EnumType.class, new Predicate() {
public boolean apply(CustomPlanks.EnumType type) { return type.getMetadata() < 4; } public boolean apply(Object p_apply_1_) { return this.apply((CustomPlanks.EnumType)p_apply_1_); } });
public static final PropertyEnum VARIANT = PropertyEnum.create("variant", CustomPlanks.EnumType.class);
public CustomPlanks()
{
super(Material.wood);
this.setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, CustomPlanks.EnumType.APPLE));
this.setCreativeTab(CreativeTabs.tabBlock);
}
/**
* Get the damage value that this Block should drop
*/
public int damageDropped(IBlockState state)
{
return ((CustomPlanks.EnumType)state.getValue(VARIANT)).getMetadata();
}
/**
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
*/
@SideOnly(Side.CLIENT)
public void getSubBlocks(Item itemIn, CreativeTabs tab, List list)
{
CustomPlanks.EnumType[] aenumtype = CustomPlanks.EnumType.values();
int i = aenumtype.length;
/**
* Convert the given metadata into a BlockState for this Block
*/
public IBlockState getStateFromMeta(int meta)
{
return this.getDefaultState().withProperty(VARIANT, CustomPlanks.EnumType.byMetadata(meta));
}
/**
* Convert the BlockState into the correct metadata value
*/
public int getMetaFromState(IBlockState state)
{
return ((CustomPlanks.EnumType)state.getValue(VARIANT)).getMetadata();
}
protected BlockState createBlockState()
{
return new BlockState(this, new IProperty[] {VARIANT});
}
public static enum EnumType implements IStringSerializable
{
APPLE(0, "apple"),
PINE(1, "pine"),
WILLOW(2, "willow");
private static final CustomPlanks.EnumType[] META_LOOKUP = new CustomPlanks.EnumType[values().length];
private final int meta;
private final String name;
private final String unlocalizedName;
Anyone care to give me a hint? I'm very interested to know where I'm going wrong here. I have a feeling it's in the CustomLog.java, maybe the area I have in bold somehow. At any rate, I'll keep on reading my ebook and working on this mod. Thanks for your time.
Your blockstates file is named apple_log.json instead of log.json (the name you registered the Block with)
If you want to have a blockstates file for each variant, register a state mapper and remove the variant property from the variants section of the blockstates files
You're registering the Block in init instead of preInit
Blocks and Items should be registered during preInit
Your Block doesn't have an unlocalised name
Use setUnlocalizedName to set its unlocalised name
Your Block doesn't use a custom ItemBlock class that can display the correct name based on the log variant
Vanilla logs use ItemMultiTexture for this, but GameRegistry can't instantiate this class properly due to the limitations of Java's reflection. I wrote a custom class for this, you can see it in the linked Gist.
You're subtracting 4 from the EnumType's metadata value in getSubBlocks
The current three enum values use metadata 0-2, so there's no need to subtract 4. Vanilla only does this in BlockNewLog, where the planks use metadata values 4-5. The log variant is stored in two bits of the metadata, so only values 0-3 can be used.
Your apple_log_side.json model extends block/cube_column instead of block/column_side
The latter is used by the side models of vanilla logs
You don't have item models for your log variants
Most blocks' item models simply extend the block model and use fixed rotation, translation and scale values for third person display
I've created a Gist here with your original code and then added the fixed code so you can see the changes.
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
I've created a Gist here with your original code and then added the fixed code so you can see the changes.
Wow, you're awesome. That's a huge help. I made the revisions that you have outlined in such detail (thanks for taking the time.) That fixed nearly everything, of course. Hooray, I have different log types now. I still need to make textures for my willow logs, though.
*Are you sure that Blocks and Items should be registered during preInit, I've had them registered in the Init in the past (other blocks) and they seemed to work fine. Is that something that they've changed with 1.8? Or do they work but not as well in the Init??
*I have an item model (mythadventure/resources/models/item/apple_log.json) but the blocks still lack textures in hand. (as items?)
I get this error in the console:
[Client thread/ERROR] [FML]: Model definition for location mythadventure:log#inventory not found
I'm not sure if that is connected to the lack texture or has to do with using the metadata/different versions of the same block.
It would seem from the blog to be a "missing model" or blockstates problem. Though my file paths seem to be correct. The item model .json seems to refer to the block model properly.
You're telling it to use the log model for the item (MythAdventure.Myth_Log.RegisterRenderer("log")), but your model's name is apple_log.
You'll actually need to register a model for each metadata value of the item using the corresponding variant name (0 = apple_log, 1 = pine_log, etc.).
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
I've been trying to make a custom log block. The block renders fine in hand, but causes a crash when placed. I've tried copying the relevant data directly from the vanilla logs .json to no avail. I'm very new to modding, so I suspect it's some simple thing I keep missing. However, I've seen some similar problems on the minecraft forge forums, although they didn't seem to directly answer my issue. Any help is welcome. Thank you for your time.
MainClass:
package net.mythadventure.mod;
@Mod(modid="mythadventure", name="Myth Adventure", version="Alpha_1.0", dependencies="required-after:FML")
public class MythAdventure
{
public static final String MODID = "mythadventure";
public static final String MODNAME = "Myth Adventure";
public static final String VERSION = "Alpha_1.0";
@Instance(value = MODID)
public static MythAdventure instance;
@SidedProxy(modId="mythadventure", clientSide="net.mythadventure.mod.ClientProxy", serverSide="net.mythadventure.mod.ServerProxy")
public static CommonProxy proxy;
public static CustomLog appleLog;
@EventHandler
public void preInit(FMLPreInitializationEvent e)
{
proxy.preInit(e);
}
@EventHandler
public void init(FMLInitializationEvent e)
{
proxy.init(e);
}
@EventHandler
public void postInit(FMLPostInitializationEvent e)
{
proxy.postInit(e);
}
}
CommonProxy:
package net.mythadventure.mod;
public class CommonProxy
{
public void preInit(FMLPreInitializationEvent e) {}
public void init(FMLInitializationEvent e)
{
MythAdventure.appleLog = new CustomLog(Material.wood, "apple_log", 2.0F, 3.25F, MythAdventure.mythadventureTab);
}
public void postInit(FMLPostInitializationEvent e) {}
}
ClientProxy:
package net.mythadventure.mod;
public class ClientProxy extends CommonProxy
{
@Override
public void preInit(FMLPreInitializationEvent e)
{
super.preInit(e);
}
@Override
public void init(FMLInitializationEvent e)
{
super.init(e);
MythAdventure.appleLog.RegisterRenderer("apple_log");
}
@Override
public void postInit(FMLPostInitializationEvent e)
{
super.postInit(e);
}
}
CustomLog:
package net.mythadventure.mod.blocks;
public CustomLog(Material material, String name, float hardness, float resistance, CreativeTabs creativetab) {
super();
this.setUnlocalizedName(name);
this.setHardness(hardness);
this.setResistance(resistance);
this.setStepSound(soundTypeWood);
this.setCreativeTab(creativetab);
GameRegistry.registerBlock(this, name);
this.dropsOnHarvest = Item.getItemFromBlock(this);
}
public void RegisterRenderer(String modelName) {
System.out.println("REGISTERING BLOCK RENDERER: " + modelName);
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(this), 0, new ModelResourceLocation(MythAdventure.MODID+":"+modelName, "inventory"));
}
public int damageDropped(IBlockState state)
{
return getMetaFromState(state.withProperty(BlockLog.LOG_AXIS, BlockLog.EnumAxis.Y));
}
public void setMaxHarvestXP(int expAmount)
{
this.maxharvestEXP = expAmount;
}
public void setDrops(Item drops)
{
this.dropsOnHarvest = drops;
}
public void setDrops(Block drops)
{
this.dropsOnHarvest = Item.getItemFromBlock(drops);
}
public void setDropMaxAmount(int dropamount)
{
this.dropamountmax = dropamount;
}
public Item getItemDropped(IBlockState state, Random rand, int fortune)
{
return this.dropsOnHarvest;
}
public int quantityDropped(Random random)
{
int amount = random.nextInt(this.dropamountmax) + 1;
return amount;
}
public int getExpDrop(IBlockAccess world, BlockPos pos, int fortune)
{
IBlockState state = world.getBlockState(pos);
Random rand = (world instanceof World) ? ((World)world).rand : new Random();
if (this.getItemDropped(state, rand, fortune) != Item.getItemFromBlock(this))
{
return MathHelper.getRandomIntegerInRange(rand, 0, this.maxharvestEXP);
}
return 0;
}
}
(blockstates)apple_log.json:
{
"variants": {
"axis=y": { "model": "mythadventure:apple_log" },
"axis=z": { "model": "mythadventure:apple_log_side" },
"axis=x": { "model": "mythadventure:apple_log_side", "y": 90 },
"axis=none": { "model": "mythadventure:apple_bark" }
}
}
(models/block)apple_log.json:
{
"parent": "block/cube_column",
"textures": {
"end": "mythadventure:blocks/log_apple_top",
"side": "mythadventure:blocks/log_apple"
}
}
(models/block)apple_log_side.json:
{
"parent": "block/cube_column",
"textures": {
"end": "mythadventure:blocks/log_apple_top",
"side": "mythadventure:blocks/log_apple"
}
}
(models/block)apple_bark.json:
{
"parent": "block/cube_all",
"textures": {
"all": "mythadventure:blocks/log_apple"
}
}
I get this error:
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#normal not found
and this crash:
Cannot set property PropertyEnum{name=axis, clazz=class net.minecraft.block.BlockLog$EnumAxis, values=[x, y, z, none]} as it does not exist in BlockState{block=mythadventure:apple_log, properties=[]}
To fix the crash, you need to override Block#createBlockState to return a new instance of BlockState with the BlockLog.LOG_AXIS property and your variant property like BlockOldLog and BlockNewLog do.
This may or may not fix the error in the console.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Here is the CustomLog class now:
package net.mythadventure.mod.blocks;
public class CustomLog extends BlockLog {
public static final PropertyEnum VARIANT = PropertyEnum.create("variant", BlockPlanks.EnumType.class, new Predicate() {
public boolean apply(BlockPlanks.EnumType type) {
return type.getMetadata() >= 4;
}
public boolean apply(Object p_apply_1_) {
return this.apply((BlockPlanks.EnumType)p_apply_1_);
}
});
public CustomLog(Material material, String name, float hardness, float resistance, CreativeTabs creativetab) {
super();
this.setUnlocalizedName(name);
this.setHardness(hardness);
this.setResistance(resistance);
this.setStepSound(soundTypeWood);
this.setCreativeTab(creativetab);
GameRegistry.registerBlock(this, name);
this.dropsOnHarvest = Item.getItemFromBlock(this);
}
public void RegisterRenderer(String modelName) {
System.out.println("REGISTERING BLOCK RENDERER: " + modelName);
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(this), 0, new ModelResourceLocation(MythAdventure.MODID+":"+modelName, "inventory"));
}
public IBlockState getStateFromMeta(int meta)
{
IBlockState iblockstate = this.getDefaultState().withProperty(VARIANT, BlockPlanks.EnumType.byMetadata((meta & 3) + 4));
switch (meta & 12)
{
case 0:
iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.Y);
break;
case 4:
iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.X);
break;
case 8:
iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.Z);
break;
default:
iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.NONE);
}
return iblockstate;
}
public int getMetaFromState(IBlockState state)
{
byte b0 = 0;
int i = b0 | ((BlockPlanks.EnumType)state.getValue(VARIANT)).getMetadata() - 4;
switch (CustomLog.SwitchEnumAxis.AXIS_LOOKUP[((BlockLog.EnumAxis)state.getValue(LOG_AXIS)).ordinal()])
{
case 1:
i |= 4;
break;
case 2:
i |= 8;
break;
case 3:
i |= 12;
}
return i;
}
public int damageDropped(IBlockState state)
{
return ((BlockPlanks.EnumType)state.getValue(VARIANT)).getMetadata() - 4;
}
static final class SwitchEnumAxis
{
static final int[] AXIS_LOOKUP = new int[BlockLog.EnumAxis.values().length];
static
{
try
{
AXIS_LOOKUP[BlockLog.EnumAxis.X.ordinal()] = 1;
}
catch (NoSuchFieldError var3)
{
;
}
try
{
AXIS_LOOKUP[BlockLog.EnumAxis.Z.ordinal()] = 2;
}
catch (NoSuchFieldError var2)
{
;
}
try
{
AXIS_LOOKUP[BlockLog.EnumAxis.NONE.ordinal()] = 3;
}
catch (NoSuchFieldError var1)
{
;
}
}
}
@Override
protected BlockState createBlockState()
{
return new BlockState(this, new IProperty[] {VARIANT, LOG_AXIS});
}
protected ItemStack createStackedBlock(IBlockState state)
{
return new ItemStack(Item.getItemFromBlock(this), 1, ((BlockPlanks.EnumType)state.getValue(VARIANT)).getMetadata() - 4);
}
private Item dropsOnHarvest;
public void setDrops(Item drops)
{
this.dropsOnHarvest = drops;
}
public void setDrops(Block drops)
{
this.dropsOnHarvest = Item.getItemFromBlock(drops);
}
public Item getItemDropped(IBlockState state, Random rand, int fortune)
{
return this.dropsOnHarvest;
}
}
That fixed the crash, but now the error is:
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=x,variant=dark_oak not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=y,variant=dark_oak not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=x,variant=acacia not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=none,variant=acacia not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=z,variant=acacia not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=z,variant=dark_oak not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=y,variant=acacia not found
[Client thread/ERROR] [FML]: Model definition for location mythadventure:apple_log#axis=none,variant=dark_oak not found
The block looks fine in hand still, but has the standard "missing texture" texture.
You should create your own enum with the appropriate values for the variant property. At the moment it's complaining because you haven't defined the model to use for the vanilla variant values.
If you want to use the blockstates file with the variant's name (e.g. apple_log.json > axis=x instead of log.json > variant=apple,axis=x), you'll need to register a custom IStateMapper like vanilla logs do in BlockModelShapes#registerAllBlocks. You should do this with Forge's ModelLoader.setCustomStateMapper method instead of vanilla's BlockModelShapes#registerBlockWithStateMapper method.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Okay, thanks so much for your help. I don't know much about coding, I've only been trying to learn it for the past few weeks. I am a disabled Army Intelligence veteran though, and I'm trying really hard to figure this stuff out. I appreciate you giving me a place to work from on fixing this.
No problem.
Do you know Java? You'll need to know it reasonably well to understand the vanilla code and make a mod.
Slightly related: You should add the @Override annotation to any override methods so the compiler ensures that they do actually override a method in a super class. If a method with @Override doesn't match any super method, you'll get a compiler error telling you.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
No. Though I do have a lot of time on my hands and I'm pretty good at figuring things out. Do you think I'd be better off starting with a Java for Dummies book or something?
I would highly recommend learning Java before trying to learn Minecraft/Forge.
Books are one option for this, there are also lots of online resources such as TheNewBoston's videos and Vswe's summer course lecture videos (covering both Java and Forge).
I personally learned Java at university after teaching myself basic programming concepts by learning Lua (for World of Warcraft AddOns, which are a lot more limited in scope than Minecraft mods), so I'm not sure how effective these videos are.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Thanks for the links and advice. I think I'll supplement my efforts at learning it as I go by reading a Java for Dummies ebook. I'll also be sure to check out those links.
I've gotten up to Chapter 6 of the Java for Dummies book. Still having learned only the very, very basics so far. I took another swing at the code for log types, using vanilla OldLogs and NewLogs for reference. I feel like I'm getting close to cracking it. I have the logs rendering when I place them, but the three types I have all use the texture for the first type "APPLE" and the block has missing texture in hand. It's also called "null" in inventory. Although when I use F3 it shows up as a log block with "variant:apple".
MainClass:
package net.mythadventure.mod;
@Mod(modid="mythadventure", name="Myth Adventure", version="Alpha_1.0", dependencies="required-after:FML")
public class MythAdventure
{
public static final String MODID = "mythadventure";
public static final String MODNAME = "Myth Adventure";
public static final String VERSION = "Alpha_1.0";
@Instance(value = MODID)
public static MythAdventure instance;
@SidedProxy(modId="mythadventure", clientSide="net.mythadventure.mod.ClientProxy", serverSide="net.mythadventure.mod.ServerProxy")
public static CommonProxy proxy;
public static CustomLog Myth_Log;
@EventHandler
public void preInit(FMLPreInitializationEvent e)
{
proxy.preInit(e);
}
@EventHandler
public void init(FMLInitializationEvent e)
{
proxy.init(e);
}
@EventHandler
public void postInit(FMLPostInitializationEvent e)
{
proxy.postInit(e);
}
}
CommonProxy:
package net.mythadventure.mod;
public class CommonProxy
{
public void preInit(FMLPreInitializationEvent e) {}
public void init(FMLInitializationEvent e)
{
MythAdventure.Myth_Log = (CustomLog) new CustomLog("log").setCreativeTab(MythAdventure.mythadventureTab);
}
public void postInit(FMLPostInitializationEvent e) {}
}
ClientProxy:
package net.mythadventure.mod;
public class ClientProxy extends CommonProxy
{
@Override
public void preInit(FMLPreInitializationEvent e)
{
super.preInit(e);
}
@Override
public void init(FMLInitializationEvent e)
{
super.init(e);
MythAdventure.Myth_Log.RegisterRenderer("log");
}
@Override
public void postInit(FMLPostInitializationEvent e)
{
super.postInit(e);
}
}
CustomLog:
package net.mythadventure.mod.blocks;
public class CustomLog extends BlockLog {
public static final PropertyEnum VARIANT = PropertyEnum.create("variant", CustomPlanks.EnumType.class, new Predicate() {
public boolean apply(CustomPlanks.EnumType type) {
return type.getMetadata() < 4;
}
public boolean apply(Object p_apply_1_) {
return this.apply((CustomPlanks.EnumType)p_apply_1_);
}
});
public CustomLog(String modelName) {
this.setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, CustomPlanks.EnumType.APPLE).withProperty(LOG_AXIS, CustomLog.EnumAxis.Y));
System.out.println("INITIALIZING BLOCK: " + modelName);
GameRegistry.registerBlock(this, modelName);
}
public void RegisterRenderer(String modelName) {
System.out.println("REGISTERING BLOCK RENDERER: " + modelName);
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(this), 0, new ModelResourceLocation(MythAdventure.MODID+":"+modelName, "inventory"));
}
@SideOnly(Side.CLIENT)
public void getSubBlocks(Item itemIn, CreativeTabs tab, List list) {
list.add(new ItemStack(itemIn, 1, CustomPlanks.EnumType.APPLE.getMetadata() - 4));
list.add(new ItemStack(itemIn, 1, CustomPlanks.EnumType.PINE.getMetadata() - 4));
list.add(new ItemStack(itemIn, 1, CustomPlanks.EnumType.WILLOW.getMetadata() - 4));
}
public IBlockState getStateFromMeta(int meta) {
IBlockState iblockstate = this.getDefaultState().withProperty(VARIANT, CustomPlanks.EnumType.byMetadata((meta & 3) + 4));
switch (meta & 12) {
case 0:
iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.Y);
break;
case 4:
iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.X);
break;
case 8:
iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.Z);
break;
default:
iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.NONE);
}
return iblockstate;
}
public int getMetaFromState(IBlockState state){
byte b0 = 0;
int i = b0 | ((CustomPlanks.EnumType)state.getValue(VARIANT)).getMetadata();
switch (CustomLog.SwitchEnumAxis.AXIS_LOOKUP[((BlockLog.EnumAxis)state.getValue(LOG_AXIS)).ordinal()]) {
case 1:
i |= 4;
break;
case 2:
i |= 8;
break;
case 3:
i |= 12;
}
return i;
}
protected BlockState createBlockState() {
return new BlockState(this, new IProperty[] {VARIANT, LOG_AXIS});
}
protected ItemStack createStackedBlock(IBlockState state) {
return new ItemStack(Item.getItemFromBlock(this), 1, ((CustomPlanks.EnumType)state.getValue(VARIANT)).getMetadata() - 4);
}
public int damageDropped(IBlockState state) {
return ((CustomPlanks.EnumType)state.getValue(VARIANT)).getMetadata() - 4;
}
static final class SwitchEnumAxis {
static final int[] AXIS_LOOKUP = new int[BlockLog.EnumAxis.values().length];
static {
try {
AXIS_LOOKUP[BlockLog.EnumAxis.X.ordinal()] = 1;
}
catch (NoSuchFieldError var3)
{ ; }
try {
AXIS_LOOKUP[BlockLog.EnumAxis.Z.ordinal()] = 2;
}
catch (NoSuchFieldError var2)
{ ; }
try {
AXIS_LOOKUP[BlockLog.EnumAxis.NONE.ordinal()] = 3;
}
catch (NoSuchFieldError var1)
{ ; }
}
}
}
CustomPlanks:
package net.mythadventure.mod.blocks;
public class CustomPlanks extends Block{
public static final PropertyEnum VARIANT = PropertyEnum.create("variant", CustomPlanks.EnumType.class);
public CustomPlanks()
{
super(Material.wood);
this.setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, CustomPlanks.EnumType.APPLE));
this.setCreativeTab(CreativeTabs.tabBlock);
}
/**
* Get the damage value that this Block should drop
*/
public int damageDropped(IBlockState state)
{
return ((CustomPlanks.EnumType)state.getValue(VARIANT)).getMetadata();
}
/**
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
*/
@SideOnly(Side.CLIENT)
public void getSubBlocks(Item itemIn, CreativeTabs tab, List list)
{
CustomPlanks.EnumType[] aenumtype = CustomPlanks.EnumType.values();
int i = aenumtype.length;
for (int j = 0; j < i; ++j)
{
CustomPlanks.EnumType enumtype = aenumtype[j];
list.add(new ItemStack(itemIn, 1, enumtype.getMetadata()));
}
}
/**
* Convert the given metadata into a BlockState for this Block
*/
public IBlockState getStateFromMeta(int meta)
{
return this.getDefaultState().withProperty(VARIANT, CustomPlanks.EnumType.byMetadata(meta));
}
/**
* Convert the BlockState into the correct metadata value
*/
public int getMetaFromState(IBlockState state)
{
return ((CustomPlanks.EnumType)state.getValue(VARIANT)).getMetadata();
}
protected BlockState createBlockState()
{
return new BlockState(this, new IProperty[] {VARIANT});
}
public static enum EnumType implements IStringSerializable
{
APPLE(0, "apple"),
PINE(1, "pine"),
WILLOW(2, "willow");
private static final CustomPlanks.EnumType[] META_LOOKUP = new CustomPlanks.EnumType[values().length];
private final int meta;
private final String name;
private final String unlocalizedName;
private EnumType(int meta, String name)
{
this(meta, name, name);
}
private EnumType(int meta, String name, String unlocalizedName)
{
this.meta = meta;
this.name = name;
this.unlocalizedName = unlocalizedName;
}
public int getMetadata()
{
return this.meta;
}
public String toString()
{
return this.name;
}
public static CustomPlanks.EnumType byMetadata(int meta)
{
if (meta < 0 || meta >= META_LOOKUP.length)
{
meta = 0;
}
return META_LOOKUP[meta];
}
public String getName()
{
return this.name;
}
public String getUnlocalizedName()
{
return this.unlocalizedName;
}
static
{
CustomPlanks.EnumType[] var0 = values();
int var1 = var0.length;
for (int var2 = 0; var2 < var1; ++var2)
{
CustomPlanks.EnumType var3 = var0[var2];
META_LOOKUP[var3.getMetadata()] = var3;
}
}
}
}
(blockstates)apple_log.json:
{
"variants": {
"axis=y,variant=apple": { "model": "mythadventure:apple_log" },
"axis=z,variant=apple": { "model": "mythadventure:apple_log_side" },
"axis=x,variant=apple": { "model": "mythadventure:apple_log_side", "y": 90 },
"axis=none,variant=apple": { "model": "mythadventure:apple_bark" },
"axis=y,variant=pine": { "model": "mythadventure:pine_log" },
"axis=z,variant=pine": { "model": "mythadventure:pine_log_side" },
"axis=x,variant=pine": { "model": "mythadventure:pine_log_side", "y": 90 },
"axis=none,variant=pine": { "model": "mythadventure:pine_bark" },
"axis=y,variant=willow": { "model": "mythadventure:willow_log" },
"axis=z,variant=willow": { "model": "mythadventure:willow_log_side" },
"axis=x,variant=willow": { "model": "mythadventure:willow_log_side", "y": 90 },
"axis=none,variant=willow": { "model": "mythadventure:willow_bark" }
}
}
(models/block)apple_log.json:
{
"parent": "block/cube_column",
"textures": {
"end": "mythadventure:blocks/log_apple_top",
"side": "mythadventure:blocks/log_apple"
}
}
(models/block)apple_log_side.json:
{
"parent": "block/cube_column",
"textures": {
"end": "mythadventure:blocks/log_apple_top",
"side": "mythadventure:blocks/log_apple"
}
}
(models/block)apple_bark.json:
{
"parent": "block/cube_all",
"textures": {
"all": "mythadventure:blocks/log_apple"
}
}
Anyone care to give me a hint? I'm very interested to know where I'm going wrong here. I have a feeling it's in the CustomLog.java, maybe the area I have in bold somehow. At any rate, I'll keep on reading my ebook and working on this mod. Thanks for your time.
You have several issues here:
I've created a Gist here with your original code and then added the fixed code so you can see the changes.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Wow, you're awesome. That's a huge help. I made the revisions that you have outlined in such detail (thanks for taking the time.) That fixed nearly everything, of course. Hooray, I have different log types now. I still need to make textures for my willow logs, though.
I made an account on GitHub and made my own Gist: My first mod Gist
*Are you sure that Blocks and Items should be registered during preInit, I've had them registered in the Init in the past (other blocks) and they seemed to work fine. Is that something that they've changed with 1.8? Or do they work but not as well in the Init??
*I have an item model (mythadventure/resources/models/item/apple_log.json) but the blocks still lack textures in hand. (as items?)
I get this error in the console:
[Client thread/ERROR] [FML]: Model definition for location mythadventure:log#inventory not found
I'm not sure if that is connected to the lack texture or has to do with using the metadata/different versions of the same block.
I checked this blog: Troubleshooting Block and Item Rendering
It would seem from the blog to be a "missing model" or blockstates problem. Though my file paths seem to be correct. The item model .json seems to refer to the block model properly.
I think the problem is with ItemBlock, maybe the ItemModMultitexture. I hope you figure it out, Mythra.
You're telling it to use the log model for the item (MythAdventure.Myth_Log.RegisterRenderer("log")), but your model's name is apple_log.
You'll actually need to register a model for each metadata value of the item using the corresponding variant name (0 = apple_log, 1 = pine_log, etc.).
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Thanks, Choonster, you rock! That was the last issue for these blocks.
For anyone interested in what worked for me, this is what I changed in the ClientProxy:
public void preInit(FMLPreInitializationEvent e)
{
super.preInit(e);
ModelBakery.addVariantName(Item.getItemFromBlock(MythAdventure.Myth_Log), new String[]{MythAdventure.MODID + ":apple_log", MythAdventure.MODID + ":pine_log", MythAdventure.MODID + ":willow_log"});
}
@Override
public void init(FMLInitializationEvent e)
{
super.init(e);
MythAdventure.Myth_Log.RegisterRenderer("log")Item log = GameRegistry.findItem(MythAdventure.MODID, "log");
registerItem(log, 0, MythAdventure.MODID + ":apple_log");
registerItem(log, 1, MythAdventure.MODID + ":pine_log");
registerItem(log, 2, MythAdventure.MODID + ":willow_log");
}
There may be a better way to do it, but this worked.