/******************************************************************************* * AbyssalCraft * Copyright (c) 2012 - 2017 Shinoow. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl-3.0.txt * * Contributors: * Shinoow - implementation ******************************************************************************/ package com.shinoow.abyssalcraft.common.blocks.tile; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.effect.EntityLightningBolt; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayer; 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.tileentity.TileEntity; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ITickable; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import com.shinoow.abyssalcraft.api.energy.EnergyEnum.DeityType; import com.shinoow.abyssalcraft.api.energy.IEnergyTransporterItem; import com.shinoow.abyssalcraft.api.energy.disruption.DisruptionHandler; import com.shinoow.abyssalcraft.api.entity.EntityUtil; import com.shinoow.abyssalcraft.api.event.ACEvents.RitualEvent; import com.shinoow.abyssalcraft.api.ritual.NecronomiconRitual; import com.shinoow.abyssalcraft.api.ritual.RitualRegistry; import com.shinoow.abyssalcraft.common.items.ItemNecronomicon; import com.shinoow.abyssalcraft.lib.ACSounds; import com.shinoow.abyssalcraft.lib.util.blocks.IRitualAltar; import com.shinoow.abyssalcraft.lib.util.blocks.IRitualPedestal; public class TileEntityRitualAltar extends TileEntity implements ITickable, IRitualAltar { private int ritualTimer; private ItemStack[] offers = new ItemStack[8]; private NecronomiconRitual ritual; private ItemStack item = ItemStack.EMPTY; private int rot; private EntityPlayer user; private float consumedEnergy; private boolean isDirty; @Override public void readFromNBT(NBTTagCompound nbttagcompound) { super.readFromNBT(nbttagcompound); NBTTagCompound nbtItem = nbttagcompound.getCompoundTag("Item"); item = new ItemStack(nbtItem); rot = nbttagcompound.getInteger("Rot"); ritualTimer = nbttagcompound.getInteger("Cooldown"); } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbttagcompound) { super.writeToNBT(nbttagcompound); NBTTagCompound nbtItem = new NBTTagCompound(); if(!item.isEmpty()) item.writeToNBT(nbtItem); nbttagcompound.setTag("Item", nbtItem); nbttagcompound.setInteger("Rot", rot); nbttagcompound.setInteger("Cooldown", ritualTimer); return nbttagcompound; } @Override public SPacketUpdateTileEntity getUpdatePacket() { return new SPacketUpdateTileEntity(pos, 1, getUpdateTag()); } @Override public NBTTagCompound getUpdateTag() { return writeToNBT(new NBTTagCompound()); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity packet) { readFromNBT(packet.getNbtCompound()); } @Override public void update() { if(isDirty || isPerformingRitual()){ world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); isDirty = false; } if(isPerformingRitual()){ if(ritualTimer == 1){ SoundEvent chant = getRandomChant(); world.playSound(pos.getX(), pos.getY(), pos.getZ(), chant, SoundCategory.PLAYERS, 1, 1, true); world.playSound(pos.getX(), pos.getY(), pos.getZ(), chant, SoundCategory.PLAYERS, 1, 1, true); world.playSound(pos.getX(), pos.getY(), pos.getZ(), chant, SoundCategory.PLAYERS, 1, 1, true); } ritualTimer++; if(ritual != null){ if(user != null){ for(ItemStack item : user.inventory.mainInventory) if(item != null && item.getItem() instanceof IEnergyTransporterItem && ((IEnergyTransporterItem) item.getItem()).canTransferPEExternally(item) && (item.getItem() instanceof ItemNecronomicon && ((ItemNecronomicon)item.getItem()).isOwner(user, item) || !(item.getItem() instanceof ItemNecronomicon))){ consumedEnergy += ((IEnergyTransporterItem) item.getItem()).consumeEnergy(item, ritual.getReqEnergy()/200); break; } } else user = world.getClosestPlayer(pos.getX(), pos.getY(), pos.getZ(), 5, true); if(ritualTimer == 200) if(user != null){ if(!MinecraftForge.EVENT_BUS.post(new RitualEvent.Post(user, ritual, world, pos))){ for(ItemStack item : user.inventory.mainInventory) if(item != null && item.getItem() instanceof IEnergyTransporterItem && ((IEnergyTransporterItem) item.getItem()).canTransferPEExternally(item) && (item.getItem() instanceof ItemNecronomicon && ((ItemNecronomicon)item.getItem()).isOwner(user, item) || !(item.getItem() instanceof ItemNecronomicon))){ consumedEnergy += ((IEnergyTransporterItem) item.getItem()).consumeEnergy(item, ritual.getReqEnergy()/200); break; } if(consumedEnergy == ritual.getReqEnergy()) ritual.completeRitual(world, pos, user); else if(!world.isRemote){ world.addWeatherEffect(new EntityLightningBolt(world, pos.getX(), pos.getY() + 1, pos.getZ(), false)); DisruptionHandler.instance().generateDisruption(DeityType.values()[world.rand.nextInt(DeityType.values().length)], world, pos, world.getEntitiesWithinAABB(EntityPlayer.class, new AxisAlignedBB(pos).expand(16, 16, 16))); } ritualTimer = 0; user = null; ritual = null; consumedEnergy = 0; isDirty = true; } } else { if(!world.isRemote){ world.addWeatherEffect(new EntityLightningBolt(world, pos.getX(), pos.getY() + 1, pos.getZ(), false)); DisruptionHandler.instance().generateDisruption(DeityType.values()[world.rand.nextInt(DeityType.values().length)], world, pos, world.getEntitiesWithinAABB(EntityPlayer.class, new AxisAlignedBB(pos).expand(16, 16, 16))); } ritualTimer = 0; ritual = null; consumedEnergy = 0; isDirty = true; } } else ritualTimer = 0; world.spawnParticle(EnumParticleTypes.LAVA, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, 0,0,0); double n = 0.25; world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() - 2.5, pos.getY() + 0.95, pos.getZ() + 0.5, n,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() + 0.5, pos.getY() + 0.95, pos.getZ() - 2.5, 0,0,n); world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() + 3.5, pos.getY() + 0.95, pos.getZ() + 0.5, -n,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() + 0.5, pos.getY() + 0.95, pos.getZ() + 3.5, 0,0,-n); world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() - 1.5, pos.getY() + 0.95, pos.getZ() + 2.5, n,0,-n); world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() - 1.5, pos.getY() + 0.95, pos.getZ() - 1.5, n,0,n); world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() + 2.5, pos.getY() + 0.95, pos.getZ() + 2.5, -n,0,-n); world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() + 2.5, pos.getY() + 0.95, pos.getZ() - 1.5, -n,0,n); world.spawnParticle(EnumParticleTypes.FLAME, pos.getX() - 2.5, pos.getY() + 1.05, pos.getZ() + 0.5, 0,0,0); world.spawnParticle(EnumParticleTypes.FLAME, pos.getX() + 0.5, pos.getY() + 1.05, pos.getZ() - 2.5, 0,0,0); world.spawnParticle(EnumParticleTypes.FLAME, pos.getX() + 3.5, pos.getY() + 1.05, pos.getZ() + 0.5, 0,0,0); world.spawnParticle(EnumParticleTypes.FLAME, pos.getX() + 0.5, pos.getY() + 1.05, pos.getZ() + 3.5, 0,0,0); world.spawnParticle(EnumParticleTypes.FLAME, pos.getX() - 1.5, pos.getY() + 1.05, pos.getZ() + 2.5, 0,0,0); world.spawnParticle(EnumParticleTypes.FLAME, pos.getX() - 1.5, pos.getY() + 1.05, pos.getZ() - 1.5, 0,0,0); world.spawnParticle(EnumParticleTypes.FLAME, pos.getX() + 2.5, pos.getY() + 1.05, pos.getZ() + 2.5, 0,0,0); world.spawnParticle(EnumParticleTypes.FLAME, pos.getX() + 2.5, pos.getY() + 1.05, pos.getZ() - 1.5, 0,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() - 2.5, pos.getY() + 1.05, pos.getZ() + 0.5, 0,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() + 0.5, pos.getY() + 1.05, pos.getZ() - 2.5, 0,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() + 3.5, pos.getY() + 1.05, pos.getZ() + 0.5, 0,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() + 0.5, pos.getY() + 1.05, pos.getZ() + 3.5, 0,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() - 1.5, pos.getY() + 1.05, pos.getZ() + 2.5, 0,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() - 1.5, pos.getY() + 1.05, pos.getZ() - 1.5, 0,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() + 2.5, pos.getY() + 1.05, pos.getZ() + 2.5, 0,0,0); world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX() + 2.5, pos.getY() + 1.05, pos.getZ() - 1.5, 0,0,0); } if(rot == 360) rot = 0; if(!item.isEmpty()) rot++; } @Override public boolean canPerform(){ if(checkSurroundings(world, pos)) return true; return false; } @Override public boolean checkSurroundings(World world, BlockPos pos){ int x = pos.getX(); int y = pos.getY(); int z = pos.getZ(); TileEntity ped1 = world.getTileEntity(new BlockPos(x - 3, y, z)); TileEntity ped2 = world.getTileEntity(new BlockPos(x, y, z - 3)); TileEntity ped3 = world.getTileEntity(new BlockPos(x + 3, y, z)); TileEntity ped4 = world.getTileEntity(new BlockPos(x, y, z + 3)); TileEntity ped5 = world.getTileEntity(new BlockPos(x - 2, y, z + 2)); TileEntity ped6 = world.getTileEntity(new BlockPos(x - 2, y, z - 2)); TileEntity ped7 = world.getTileEntity(new BlockPos(x + 2, y, z + 2)); TileEntity ped8 = world.getTileEntity(new BlockPos(x + 2, y, z - 2)); if(ped1 != null && ped2 != null && ped3 != null && ped4 != null && ped5 != null && ped6 != null && ped7 != null && ped8 != null) if(ped1 instanceof IRitualPedestal && ped2 instanceof IRitualPedestal && ped3 instanceof IRitualPedestal && ped4 instanceof IRitualPedestal && ped5 instanceof IRitualPedestal && ped6 instanceof IRitualPedestal && ped7 instanceof IRitualPedestal && ped8 instanceof IRitualPedestal){ offers[0] = ((IRitualPedestal)ped1).getItem(); offers[1] = ((IRitualPedestal)ped2).getItem(); offers[2] = ((IRitualPedestal)ped3).getItem(); offers[3] = ((IRitualPedestal)ped4).getItem(); offers[4] = ((IRitualPedestal)ped5).getItem(); offers[5] = ((IRitualPedestal)ped6).getItem(); offers[6] = ((IRitualPedestal)ped7).getItem(); offers[7] = ((IRitualPedestal)ped8).getItem(); if(offers[0].isEmpty() && offers[1].isEmpty() && offers[2].isEmpty() && offers[3].isEmpty() && offers[4].isEmpty() && offers[5].isEmpty() && offers[6].isEmpty() && offers[7].isEmpty()) return false; else return true; } return false; } @Override public void resetPedestals(World world, BlockPos pos){ int x = pos.getX(); int y = pos.getY(); int z = pos.getZ(); TileEntity ped1 = world.getTileEntity(new BlockPos(x-3, y, z)); TileEntity ped2 = world.getTileEntity(new BlockPos(x, y, z - 3)); TileEntity ped3 = world.getTileEntity(new BlockPos(x + 3, y, z)); TileEntity ped4 = world.getTileEntity(new BlockPos(x, y, z + 3)); TileEntity ped5 = world.getTileEntity(new BlockPos(x - 2, y, z + 2)); TileEntity ped6 = world.getTileEntity(new BlockPos(x - 2, y, z - 2)); TileEntity ped7 = world.getTileEntity(new BlockPos(x + 2, y, z + 2)); TileEntity ped8 = world.getTileEntity(new BlockPos(x + 2, y, z - 2)); if(ped1 != null && ped2 != null && ped3 != null && ped4 != null && ped5 != null && ped6 != null && ped7 != null && ped8 != null) if(ped1 instanceof IRitualPedestal && ped2 instanceof IRitualPedestal && ped3 instanceof IRitualPedestal && ped4 instanceof IRitualPedestal && ped5 instanceof IRitualPedestal && ped6 instanceof IRitualPedestal && ped7 instanceof IRitualPedestal && ped8 instanceof IRitualPedestal){ ((IRitualPedestal)ped1).setItem(getStack(((IRitualPedestal)ped1).getItem())); ((IRitualPedestal)ped2).setItem(getStack(((IRitualPedestal)ped2).getItem())); ((IRitualPedestal)ped3).setItem(getStack(((IRitualPedestal)ped3).getItem())); ((IRitualPedestal)ped4).setItem(getStack(((IRitualPedestal)ped4).getItem())); ((IRitualPedestal)ped5).setItem(getStack(((IRitualPedestal)ped5).getItem())); ((IRitualPedestal)ped6).setItem(getStack(((IRitualPedestal)ped6).getItem())); ((IRitualPedestal)ped7).setItem(getStack(((IRitualPedestal)ped7).getItem())); ((IRitualPedestal)ped8).setItem(getStack(((IRitualPedestal)ped8).getItem())); } } private ItemStack getStack(ItemStack stack){ if(!stack.isEmpty() && stack.getItem().hasContainerItem(stack)) return stack.getItem().getContainerItem(stack); else return ItemStack.EMPTY; } @Override public void performRitual(World world, BlockPos pos, EntityPlayer player){ if(!isPerformingRitual()){ ItemStack item = player.getHeldItemMainhand(); if(item.getItem() instanceof ItemNecronomicon && ((ItemNecronomicon)item.getItem()).isOwner(player, item)) if(RitualRegistry.instance().canPerformAction(world.provider.getDimension(), ((ItemNecronomicon)item.getItem()).getBookType())) if(canPerform()){ ritual = RitualRegistry.instance().getRitual(world.provider.getDimension(), ((ItemNecronomicon)item.getItem()).getBookType(), offers, this.item); if(ritual != null) if(ritual.requiresSacrifice()){ if(!world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(pos).expand(4, 4, 4)).isEmpty()) for(EntityLivingBase mob : world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(pos).expand(4, 4, 4))) if(canBeSacrificed(mob)) if(ritual.canCompleteRitual(world, pos, player)) if(!MinecraftForge.EVENT_BUS.post(new RitualEvent.Pre(player, ritual, world, pos))){ if(!world.isRemote){ mob.setDead(); world.addWeatherEffect(new EntityLightningBolt(world, mob.posX, mob.posY, mob.posZ, false)); } ritualTimer = 1; resetPedestals(world, pos); user = player; consumedEnergy = 0; isDirty = true; } } else if(ritual.canCompleteRitual(world, pos, player)) if(!MinecraftForge.EVENT_BUS.post(new RitualEvent.Pre(player, ritual, world, pos))){ ritualTimer = 1; resetPedestals(world, pos); user = player; consumedEnergy = 0; isDirty = true; } } } } /** * Checks if a certain Entity can be sacrificed * @param entity Entity to potentially sacrifice * @return True if the Entity can be sacrificed, otherwise false */ private boolean canBeSacrificed(EntityLivingBase entity){ return !(entity instanceof EntityPlayer) && (EntityUtil.isShoggothFood(entity) || entity instanceof EntityVillager) && entity.getCreatureAttribute() != EnumCreatureAttribute.UNDEAD && entity.isEntityAlive() && !entity.isChild(); } public SoundEvent getRandomChant(){ SoundEvent[] chants = {ACSounds.cthulhu_chant, ACSounds.yog_sothoth_chant_1, ACSounds.yog_sothoth_chant_2, ACSounds.hastur_chant_1, ACSounds.hastur_chant_2, ACSounds.sleeping_chant, ACSounds.cthugha_chant}; return chants[world.rand.nextInt(chants.length)]; } @Override public int getRitualCooldown(){ return ritualTimer; } @Override public boolean isPerformingRitual(){ return ritualTimer < 200 && ritualTimer > 0; } @Override public int getRotation(){ return rot; } @Override public ItemStack getItem(){ return item; } @Override public void setItem(ItemStack item){ this.item = item; isDirty = true; } }