-
Notifications
You must be signed in to change notification settings - Fork 24
Integrating food items with AppleCore
If you want your food to integrate with AppleCore, do not call FoodStats.addStats(int, float)
when it is eaten. Use the ItemStack-aware FoodStats.func_151686_a(ItemFood, ItemStack)
method instead.
If your food extends ItemFood and uses the standard Minecraft ItemFood methods, your food will integrate with AppleCore without issue.
- Have your item extend
ItemFood
. - Use the ItemStack-aware hunger and saturation getters (
getHealAmount
/func_150905_g
for hunger value andgetSaturationModifier
/func_150906_h
for the saturation modifier). - Use the default
ItemFood.onEaten
(1.7.10) /ItemFood.onItemUseFinish
(1.8+) implementation or make sure that your overridden version still callsFoodStats.func_151686_a(ItemFood, ItemStack)
(the ItemStack-aware version ofFoodStats.addStats
).
That's it. Your food will integrate properly with AppleCore if you're able to check off all of the above. If you want to use metadata-based food items, you can find an example AppleCore-compatible implementation in the example package.
If your food does not extend ItemFood
, then you can implement AppleCore's IEdible
interface and use ItemFoodProxy
to call FoodStats.func_151686_a(ItemFood, ItemStack)
when the food is eaten.
Here is an example implementation with the irrelevant parts removed (full implementation):
@Optional.Interface(iface = "squeek.applecore.api.food.IEdible", modid = "AppleCore")
public class ItemNonStandardFood extends Item implements IEdible
{
@Optional.Method(modid = "AppleCore")
@Override
public FoodValues getFoodValues(ItemStack itemStack)
{
return new FoodValues(1, 1f);
}
// This needs to be abstracted into an Optional method,
// otherwise the ItemFoodProxy reference will cause problems
@Optional.Method(modid = "AppleCore")
public void onEatenCompatibility(ItemStack itemStack, EntityPlayer player)
{
// one possible compatible method
player.getFoodStats().func_151686_a(new ItemFoodProxy(this), itemStack);
// another possible compatible method:
// new ItemFoodProxy(this).onEaten(itemStack, player);
}
@Override
// this method was called onEaten in 1.7.10
public ItemStack onItemUseFinish(ItemStack itemStack, World world, EntityPlayer player)
{
--itemStack.stackSize;
if (Loader.isModLoaded("AppleCore"))
{
onEatenCompatibility(itemStack, player);
}
else
{
// this method is not compatible with AppleCore
player.getFoodStats().addStats(1, 1f);
}
return itemStack;
}
}
Note also that the above example degrades nicely: if AppleCore is not loaded, it will still function as expected.
Foods are considered inedible, and therefore will return false
when passed to AppleCoreAPI.accessor.isFood
if the Item implementation does not return EnumAction.EAT
or EnumAction.DRINK
from Item.getItemUseAction
.
public class ItemFoodEdibleSometimes extends ItemFood
{
@Override
public EnumAction getItemUseAction(ItemStack itemStack)
{
return someCondition(itemStack) ? EnumAction.EAT : EnumAction.NONE;
}
}
To mark a block as edible, have its Block
class implement IEdibleBlock
. Here is an example implementation with the irrelevant parts removed (full implementation):
@Optional.Interface(iface = "squeek.applecore.api.food.IEdibleBlock", modid = "AppleCore")
public class BlockEdibleExample extends Block implements IEdibleBlock
{
private boolean isEdibleAtMaxHunger = false;
@Optional.Method(modid = "AppleCore")
@Override
public void setEdibleAtMaxHunger(boolean value)
{
isEdibleAtMaxHunger = value;
}
@Optional.Method(modid = "AppleCore")
@Override
public FoodValues getFoodValues(ItemStack itemStack)
{
return new FoodValues(2, 0.1f);
}
// This needs to be abstracted into an Optional method,
// otherwise the ItemFoodProxy reference will cause problems
@Optional.Method(modid = "AppleCore")
public void onEatenCompatibility(ItemStack itemStack, EntityPlayer player)
{
// one possible compatible method
player.getFoodStats().addStats(new ItemFoodProxy(this), itemStack);
// another possible compatible method:
// new ItemFoodProxy(this).onEaten(itemStack, player);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ)
{
if (player.canEat(isEdibleAtMaxHunger))
{
if (Loader.isModLoaded("AppleCore"))
{
onEatenCompatibility(new ItemStack(this), player);
}
else
{
// this method is not compatible with AppleCore
player.getFoodStats().addStats(2, 0.1f);
}
}
return true;
}
}
If your Block
is registered with an ItemBlock
counterpart, then that's all that is needed. However, if your Block
and Item
are not registered together (e.g. like Minecraft's cake, where Item.getItemFromBlock(Blocks.CAKE)
returns null
), then you need to register the Item
<-> Block
relationship with AppleCore like so (see IAppleCoreRegistry for more info):
AppleCoreAPI.registry.registerEdibleBlock(block, item);