/**
* This class was created by <Vazkii>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Jan 21, 2014, 7:51:36 PM (GMT)]
*/
package vazkii.botania.common.block.tile;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.IItemHandlerModifiable;
import vazkii.botania.api.BotaniaAPI;
import vazkii.botania.api.internal.VanillaPacketDispatcher;
import vazkii.botania.api.item.IPetalApothecary;
import vazkii.botania.api.recipe.IFlowerComponent;
import vazkii.botania.api.recipe.RecipePetals;
import vazkii.botania.api.sound.BotaniaSoundEvents;
import vazkii.botania.api.state.BotaniaStateProps;
import vazkii.botania.api.state.enums.AltarVariant;
import vazkii.botania.client.core.handler.HUDHandler;
import vazkii.botania.client.core.helper.RenderHelper;
import vazkii.botania.common.Botania;
import vazkii.botania.common.block.ModBlocks;
import vazkii.botania.common.network.PacketBotaniaEffect;
import vazkii.botania.common.network.PacketHandler;
import javax.annotation.Nonnull;
public class TileAltar extends TileSimpleInventory implements IPetalApothecary {
private static final Pattern SEED_PATTERN = Pattern.compile("(?:(?:(?:[A-Z-_.:]|^)seed)|(?:(?:[a-z-_.:]|^)Seed))(?:[sA-Z-_.:]|$)");
private static final int SET_KEEP_TICKS_EVENT = 0;
public static final String TAG_HAS_WATER = "hasWater";
public static final String TAG_HAS_LAVA = "hasLava";
public static final String TAG_IS_MOSSY = "isMossy";
public boolean hasWater = false;
public boolean hasLava = false;
public boolean isMossy = false;
List<ItemStack> lastRecipe = null;
int recipeKeepTicks = 0;
public boolean collideEntityItem(EntityItem item) {
ItemStack stack = item.getEntityItem();
if(world.isRemote || stack.isEmpty() || item.isDead)
return false;
if(!isMossy && world.getBlockState(getPos()).getValue(BotaniaStateProps.ALTAR_VARIANT) == AltarVariant.DEFAULT) {
if(stack.getItem() == Item.getItemFromBlock(Blocks.VINE)) {
isMossy = true;
world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock());
stack.shrink(1);
return true;
}
}
if(!hasWater() && !hasLava()) {
if(stack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null)) {
IFluidHandlerItem fluidHandler = stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null);
FluidStack drainWater = fluidHandler.drain(new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME), false);
FluidStack drainLava = fluidHandler.drain(new FluidStack(FluidRegistry.LAVA, Fluid.BUCKET_VOLUME), false);
if(drainWater != null && drainWater.getFluid() == FluidRegistry.WATER && drainWater.amount == Fluid.BUCKET_VOLUME) {
setWater(true);
world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock());
fluidHandler.drain(new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME), true);
item.setEntityItemStack(fluidHandler.getContainer());
return true;
} else if(drainLava != null && drainLava.getFluid() == FluidRegistry.LAVA && drainLava.amount == Fluid.BUCKET_VOLUME) {
setLava(true);
world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock());
fluidHandler.drain(new FluidStack(FluidRegistry.LAVA, Fluid.BUCKET_VOLUME), true);
item.setEntityItemStack(fluidHandler.getContainer());
return true;
}
}
return false;
}
if(hasLava()) {
item.setFire(100);
return true;
}
boolean didChange = false;
if(stack.getItem() instanceof IFlowerComponent && ((IFlowerComponent) stack.getItem()).canFit(stack, this)) {
if(!itemHandler.getStackInSlot(getSizeInventory() - 1).isEmpty())
return false;
for(int i = 0; i < getSizeInventory(); i++)
if(itemHandler.getStackInSlot(i).isEmpty()) {
itemHandler.setStackInSlot(i, stack.splitStack(1));
didChange = true;
world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_SPLASH, SoundCategory.BLOCKS, 0.1F, 10F);
break;
}
} else if(!stack.isEmpty() && SEED_PATTERN.matcher(stack.getItem().getUnlocalizedName(stack)).find()) {
for(RecipePetals recipe : BotaniaAPI.petalRecipes) {
if(recipe.matches(itemHandler)) {
saveLastRecipe();
for(int i = 0; i < getSizeInventory(); i++)
itemHandler.setStackInSlot(i, ItemStack.EMPTY);
stack.shrink(1);
ItemStack output = recipe.getOutput().copy();
EntityItem outputItem = new EntityItem(world, pos.getX() + 0.5, pos.getY() + 1.5, pos.getZ() + 0.5, output);
world.spawnEntity(outputItem);
setWater(false);
world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock());
craftingFanciness();
didChange = true;
break;
}
}
}
return didChange;
}
public void saveLastRecipe() {
lastRecipe = new ArrayList<>();
for(int i = 0; i < getSizeInventory(); i++) {
ItemStack stack = itemHandler.getStackInSlot(i);
if(stack.isEmpty())
break;
lastRecipe.add(stack.copy());
}
recipeKeepTicks = 400;
world.addBlockEvent(getPos(), ModBlocks.altar, SET_KEEP_TICKS_EVENT, 400);
}
public void trySetLastRecipe(EntityPlayer player) {
tryToSetLastRecipe(player, itemHandler, lastRecipe);
if(!isEmpty())
VanillaPacketDispatcher.dispatchTEToNearbyPlayers(world, pos);
}
public static void tryToSetLastRecipe(EntityPlayer player, IItemHandlerModifiable inv, List<ItemStack> lastRecipe) {
if(lastRecipe == null || lastRecipe.isEmpty() || player.world.isRemote)
return;
int index = 0;
boolean didAny = false;
for(ItemStack stack : lastRecipe) {
if(stack.isEmpty())
continue;
for(int i = 0; i < player.inventory.getSizeInventory(); i++) {
ItemStack pstack = player.inventory.getStackInSlot(i);
if(!pstack.isEmpty() && pstack.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(stack, pstack)) {
inv.setStackInSlot(index, pstack.splitStack(1));
didAny = true;
index++;
break;
}
}
}
if(didAny) {
player.world.playSound(null, player.posX, player.posY, player.posZ, SoundEvents.ENTITY_GENERIC_SPLASH, SoundCategory.BLOCKS, 0.1F, 10F);
EntityPlayerMP mp = (EntityPlayerMP) player;
mp.inventoryContainer.detectAndSendChanges();
}
}
private void craftingFanciness() {
world.playSound(null, pos, BotaniaSoundEvents.altarCraft, SoundCategory.BLOCKS, 1F, 1F);
PacketHandler.sendToNearby(world, getPos(),
new PacketBotaniaEffect(PacketBotaniaEffect.EffectType.APOTHECARY_CRAFT, getPos().getX(), getPos().getY(), getPos().getZ()));
}
public boolean isEmpty() {
for(int i = 0; i < getSizeInventory(); i++)
if(!itemHandler.getStackInSlot(i).isEmpty())
return false;
return true;
}
@Override
public void update() {
if(!world.isRemote) {
List<EntityItem> items = world.getEntitiesWithinAABB(EntityItem.class, new AxisAlignedBB(pos.add(0, 1D / 16D * 20D, 0), pos.add(1, 1D / 16D * 32D, 1)));
boolean didChange = false;
for(EntityItem item : items)
didChange = collideEntityItem(item) || didChange;
if(didChange)
VanillaPacketDispatcher.dispatchTEToNearbyPlayers(world, pos);
} else {
for(int i = 0; i < getSizeInventory(); i++) {
ItemStack stackAt = itemHandler.getStackInSlot(i);
if(stackAt.isEmpty())
break;
if(Math.random() >= 0.97) {
Color color = new Color(((IFlowerComponent) stackAt.getItem()).getParticleColor(stackAt));
float red = color.getRed() / 255F;
float green = color.getGreen() / 255F;
float blue = color.getBlue() / 255F;
if(Math.random() >= 0.75F)
world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_SPLASH, SoundCategory.BLOCKS, 0.1F, 10F);
Botania.proxy.sparkleFX(pos.getX() + 0.5 + Math.random() * 0.4 - 0.2, pos.getY() + 1, pos.getZ() + 0.5 + Math.random() * 0.4 - 0.2, red, green, blue, (float) Math.random(), 10);
}
}
if(hasLava()) {
isMossy = false;
world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() + 0.5 + Math.random() * 0.4 - 0.2, pos.getY() + 1, pos.getZ() + 0.5 + Math.random() * 0.4 - 0.2, 0, 0.05, 0);
if(Math.random() > 0.9)
world.spawnParticle(EnumParticleTypes.LAVA, pos.getX() + 0.5 + Math.random() * 0.4 - 0.2, pos.getY() + 1, pos.getZ() + 0.5 + Math.random() * 0.4 - 0.2, 0, 0.01, 0);
}
}
if(recipeKeepTicks > 0)
--recipeKeepTicks;
else lastRecipe = null;
}
@Override
public void writePacketNBT(NBTTagCompound cmp) {
super.writePacketNBT(cmp);
cmp.setBoolean(TAG_HAS_WATER, hasWater());
cmp.setBoolean(TAG_HAS_LAVA, hasLava());
cmp.setBoolean(TAG_IS_MOSSY, isMossy);
}
@Override
public void readPacketNBT(NBTTagCompound cmp) {
super.readPacketNBT(cmp);
hasWater = cmp.getBoolean(TAG_HAS_WATER);
hasLava = cmp.getBoolean(TAG_HAS_LAVA);
isMossy = cmp.getBoolean(TAG_IS_MOSSY);
}
@Override
public void onDataPacket(NetworkManager manager, SPacketUpdateTileEntity packet) {
boolean lastMossy = isMossy;
super.onDataPacket(manager, packet);
if(isMossy != lastMossy)
world.markBlockRangeForRenderUpdate(pos, pos);
}
@Override
public boolean receiveClientEvent(int id, int param) {
if(id == SET_KEEP_TICKS_EVENT) {
recipeKeepTicks = param;
return true;
} else {
return false;
}
}
@Override
public int getSizeInventory() {
return 16;
}
@Override
protected SimpleItemStackHandler createItemHandler() {
return new SimpleItemStackHandler(this, false) {
@Override
protected int getStackLimit(int slot, @Nonnull ItemStack stack) {
return 1;
}
};
}
@Override
public void setWater(boolean water) {
hasWater = water;
VanillaPacketDispatcher.dispatchTEToNearbyPlayers(world, pos);
}
public void setLava(boolean lava) {
hasLava = lava;
VanillaPacketDispatcher.dispatchTEToNearbyPlayers(world, pos);
}
@Override
public boolean hasWater() {
return hasWater;
}
public boolean hasLava() {
return hasLava;
}
@SideOnly(Side.CLIENT)
public void renderHUD(Minecraft mc, ScaledResolution res) {
int xc = res.getScaledWidth() / 2;
int yc = res.getScaledHeight() / 2;
float angle = -90;
int radius = 24;
int amt = 0;
for(int i = 0; i < getSizeInventory(); i++) {
if(itemHandler.getStackInSlot(i).isEmpty())
break;
amt++;
}
if(amt > 0) {
float anglePer = 360F / amt;
for(RecipePetals recipe : BotaniaAPI.petalRecipes)
if(recipe.matches(itemHandler)) {
GlStateManager.color(1F, 1F, 1F, 1F);
mc.renderEngine.bindTexture(HUDHandler.manaBar);
RenderHelper.drawTexturedModalRect(xc + radius + 9, yc - 8, 0, 0, 8, 22, 15);
ItemStack stack = recipe.getOutput();
net.minecraft.client.renderer.RenderHelper.enableGUIStandardItemLighting();
mc.getRenderItem().renderItemIntoGUI(stack, xc + radius + 32, yc - 8);
mc.getRenderItem().renderItemIntoGUI(new ItemStack(Items.WHEAT_SEEDS), xc + radius + 16, yc + 6);
net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting();
mc.fontRendererObj.drawStringWithShadow("+", xc + radius + 14, yc + 10, 0xFFFFFF);
}
net.minecraft.client.renderer.RenderHelper.enableGUIStandardItemLighting();
for(int i = 0; i < amt; i++) {
double xPos = xc + Math.cos(angle * Math.PI / 180D) * radius - 8;
double yPos = yc + Math.sin(angle * Math.PI / 180D) * radius - 8;
GlStateManager.translate(xPos, yPos, 0);
mc.getRenderItem().renderItemIntoGUI(itemHandler.getStackInSlot(i), 0, 0);
GlStateManager.translate(-xPos, -yPos, 0);
angle += anglePer;
}
net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting();
} else if(recipeKeepTicks > 0 && hasWater) {
String s = I18n.format("botaniamisc.altarRefill0");
mc.fontRendererObj.drawStringWithShadow(s, xc - mc.fontRendererObj.getStringWidth(s) / 2, yc + 10, 0xFFFFFF);
s = I18n.format("botaniamisc.altarRefill1");
mc.fontRendererObj.drawStringWithShadow(s, xc - mc.fontRendererObj.getStringWidth(s) / 2, yc + 20, 0xFFFFFF);
}
}
}