Package vazkii.botania.common.block.tile

Source Code of vazkii.botania.common.block.tile.TileEnchanter

/**
* 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 a
* Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License
* (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB)
*
* File Created @ [Mar 15, 2014, 4:57:52 PM (GMT)]
*/
package vazkii.botania.common.block.tile;

import java.util.ArrayList;
import java.util.List;

import net.minecraft.block.Block;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import vazkii.botania.api.mana.IManaPool;
import vazkii.botania.api.mana.spark.ISparkAttachable;
import vazkii.botania.api.mana.spark.ISparkEntity;
import vazkii.botania.api.mana.spark.SparkHelper;
import vazkii.botania.common.Botania;
import vazkii.botania.common.block.ModBlocks;

public class TileEnchanter extends TileMod implements ISparkAttachable {

  private static final String TAG_STAGE = "stage";
  private static final String TAG_STAGE_TICKS = "stageTicks";
  private static final String TAG_STAGE_3_END_TICKS = "stage3EndTicks";
  private static final String TAG_MANA_REQUIRED = "manaRequired";
  private static final String TAG_MANA = "mana";
  private static final String TAG_ITEM = "item";
  private static final String TAG_ENCHANTS = "enchantsToApply";

  public int stage = 0;
  public int stageTicks = 0;

  public int stage3EndTicks = 0;

  int manaRequired = -1;
  int mana = 0;

  public ItemStack itemToEnchant = null;
  List<EnchantmentData> enchants = new ArrayList();

  private static final int[][] OBSIDIAN_LOCATIONS = new int[][] {
    { 0, -1, 0 },
    { 0, -1, 1 }, { 0, -1, -1 }, { 1, -1, 0 }, { -1, -1, 0 },
    { 0, -1, 2 }, { -1, -1, 2 }, { 1, -1, 2 },
    { 0, -1, -2 }, { -1, -1, -2 }, { 1, -1, -2 },
    { 2, -1, 0 }, { 2, -1, 1 }, { 2, -1, -1 },
    { -2, -1, 0 }, { -2, -1, 1 }, { -2, -1, -1 }
  };

  private static final int[][][] PYLON_LOCATIONS = new int[][][] {
    { { -5, 1, 0 }, { 5, 1, 0 }, { -4, 1, 3 }, { 4, 1, 3 }, { -4, 1, -3 }, { 4, 1, -3 } },
    { { 0, 1, -5 }, { 0, 1, 5 }, { 3, 1, -4 }, { 3, 1, 4 }, { -3, 1, -4 }, { -3, 1, 4 } }
  };

  private static final int[][] FLOWER_LOCATIONS = new int[][] {
    { -1, 0, -1 }, { 1, 0, -1 }, { -1, 0, 1 }, { 1, 0, 1 }
  };

  public void onWanded(EntityPlayer player, ItemStack wand) {
    if(stage != 0 || itemToEnchant == null || !itemToEnchant.isItemEnchantable())
      return;

    List<EntityItem> items = worldObj.getEntitiesWithinAABB(EntityItem.class, AxisAlignedBB.getBoundingBox(xCoord - 2, yCoord, zCoord - 2, xCoord + 3, yCoord + 1, zCoord + 3));
    int count = items.size();

    if(count > 0 && !worldObj.isRemote) {
      for(EntityItem entity : items) {
        ItemStack item = entity.getEntityItem();
        if(item.getItem() == Items.enchanted_book) {
          NBTTagList enchants = Items.enchanted_book.func_92110_g(item);
          if(enchants != null && enchants.tagCount() > 0) {
            NBTTagCompound enchant = enchants.getCompoundTagAt(0);
            short id = enchant.getShort("id");
            if(isEnchantmentValid(id)) {
              advanceStage();
              return;
            }
          }
        }
      }
    }
  }

  @Override
  public void updateEntity() {
    if(!canEnchanterExist(worldObj, xCoord, yCoord, zCoord, getBlockMetadata())) {
      if(getBlockMetadata() < PYLON_LOCATIONS.length)
        for(int[] pylon : PYLON_LOCATIONS[getBlockMetadata()]) {
          TileEntity tile = worldObj.getTileEntity(xCoord + pylon[0], yCoord + pylon[1], zCoord + pylon[2]);
          if(tile != null && tile instanceof TilePylon)
            ((TilePylon) tile).activated = false;
        }

      worldObj.setBlock(xCoord, yCoord, zCoord, Blocks.lapis_block, 0, 1 | 2);
      for(int i = 0; i < 50; i++) {
        float red = (float) Math.random();
        float green = (float) Math.random();
        float blue = (float) Math.random();
        Botania.proxy.wispFX(worldObj, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, red, green, blue, (float) Math.random() * 0.15F + 0.15F, (float) (Math.random() - 0.5F) * 0.25F, (float) (Math.random() - 0.5F) * 0.25F, (float) (Math.random() - 0.5F) * 0.25F);
      }
      worldObj.playSoundEffect(xCoord, yCoord, zCoord, "botania:enchanterBlock", 0.5F, 10F);
    }

    switch(stage) {
    case 1 : { // Get books
      if(stageTicks % 20 == 0) {
        List<EntityItem> items = worldObj.getEntitiesWithinAABB(EntityItem.class, AxisAlignedBB.getBoundingBox(xCoord - 2, yCoord, zCoord - 2, xCoord + 3, yCoord + 1, zCoord + 3));
        int count = items.size();
        boolean addedEnch = false;

        if(count > 0 && !worldObj.isRemote) {
          for(EntityItem entity : items) {
            ItemStack item = entity.getEntityItem();
            if(item.getItem() == Items.enchanted_book) {
              NBTTagList enchants = Items.enchanted_book.func_92110_g(item);
              if(enchants != null && enchants.tagCount() > 0) {
                NBTTagCompound enchant = enchants.getCompoundTagAt(0);
                short enchantId = enchant.getShort("id");
                short enchantLvl = enchant.getShort("lvl");
                if(!hasEnchantAlready(enchantId) && isEnchantmentValid(enchantId)) {
                  this.enchants.add(new EnchantmentData(enchantId, enchantLvl));
                  worldObj.playSoundEffect(xCoord, yCoord, zCoord, "botania:ding", 1F, 1F);
                  addedEnch = true;
                  break;
                }
              }
            }
          }
        }

        if(!addedEnch) {
          if(enchants.isEmpty())
            stage = 0;
          else advanceStage();
        }
      }
      break;
    }
    case 2 : { // Get Mana
      for(int[] pylon : PYLON_LOCATIONS[getBlockMetadata()]) {
        TilePylon pylonTile = (TilePylon) worldObj.getTileEntity(xCoord + pylon[0], yCoord + pylon[1], zCoord + pylon[2]);
        if(pylonTile != null) {
          pylonTile.activated = true;
          pylonTile.centerX = xCoord;
          pylonTile.centerY = yCoord;
          pylonTile.centerZ = zCoord;
        }
      }

      if(manaRequired == -1) {
        manaRequired = 0;
        for(EnchantmentData data : enchants) {
          Enchantment ench = Enchantment.enchantmentsList[data.enchant];
          manaRequired += (int) (5000F * ((15 - Math.min(15, ench.getWeight())) * 1.05F) * ((3F + data.level * data.level) * 0.25F) * (0.9F + enchants.size() * 0.05F));
        }
      } else if(mana >= manaRequired) {
        manaRequired = 0;
        for(int[] pylon : PYLON_LOCATIONS[getBlockMetadata()])
          ((TilePylon) worldObj.getTileEntity(xCoord + pylon[0], yCoord + pylon[1], zCoord + pylon[2])).activated = false;

        advanceStage();
      } else {
        ISparkEntity spark = getAttachedSpark();
        if(spark != null) {
          List<ISparkEntity> sparkEntities = SparkHelper.getSparksAround(worldObj, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5);
          for(ISparkEntity otherSpark : sparkEntities) {
            if(spark == otherSpark)
              continue;

            if(otherSpark.getAttachedTile() != null && otherSpark.getAttachedTile() instanceof IManaPool)
              otherSpark.registerTransfer(spark);
          }
        }
      }

      break;
    }
    case 3 : { // Enchant
      if(stageTicks >= 100) {
        for(EnchantmentData data : enchants)
          itemToEnchant.addEnchantment(Enchantment.enchantmentsList[data.enchant], data.level);

        enchants.clear();
        manaRequired = -1;
        mana = 0;

        craftingFanciness();
        advanceStage();
      }
      break;
    }
    case 4 : { // Reset
      if(stageTicks >= 20)
        advanceStage();

      break;
    }
    }

    if(stage != 0)
      stageTicks++;
  }

  public void advanceStage() {
    stage++;

    if(stage == 4)
      stage3EndTicks = stageTicks;
    else if(stage == 5) {
      stage = 0;
      stage3EndTicks = 0;
    }

    stageTicks = 0;
    sync();
  }

  public void craftingFanciness() {
    worldObj.playSoundEffect(xCoord, yCoord, zCoord, "botania:enchanterEnchant", 1F, 1F);
    for(int i = 0; i < 25; i++) {
      float red = (float) Math.random();
      float green = (float) Math.random();
      float blue = (float) Math.random();
      Botania.proxy.sparkleFX(worldObj, xCoord + 0.5 + Math.random() * 0.4 - 0.2, yCoord + 1, zCoord + 0.5 + Math.random() * 0.4 - 0.2, red, green, blue, (float) Math.random(), 10);
    }
  }

  @Override
  public AxisAlignedBB getRenderBoundingBox() {
    return INFINITE_EXTENT_AABB;
  }

  @Override
  public int getCurrentMana() {
    return mana;
  }

  @Override
  public boolean isFull() {
    return mana >= manaRequired;
  }

  @Override
  public void recieveMana(int mana) {
    this.mana = Math.min(manaRequired, this.mana + mana);
  }

  @Override
  public boolean canRecieveManaFromBursts() {
    return manaRequired > 0;
  }

  public void sync() {
    worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
  }

  @Override
  public void writeCustomNBT(NBTTagCompound cmp) {
    cmp.setInteger(TAG_MANA, mana);
    cmp.setInteger(TAG_MANA_REQUIRED, manaRequired);
    cmp.setInteger(TAG_STAGE, stage);
    cmp.setInteger(TAG_STAGE_TICKS, stageTicks);
    cmp.setInteger(TAG_STAGE_3_END_TICKS, stage3EndTicks);

    NBTTagCompound itemCmp = new NBTTagCompound();
    if(itemToEnchant != null)
      itemToEnchant.writeToNBT(itemCmp);
    cmp.setTag(TAG_ITEM, itemCmp);

    String enchStr = "";
    for(EnchantmentData data : enchants)
      enchStr = enchStr + data.enchant + ":" + data.level + ",";
    cmp.setString(TAG_ENCHANTS, enchStr.isEmpty() ? enchStr : enchStr.substring(0, enchStr.length() - 1));
  }

  @Override
  public void readCustomNBT(NBTTagCompound cmp) {
    mana = cmp.getInteger(TAG_MANA);
    manaRequired = cmp.getInteger(TAG_MANA_REQUIRED);
    stage = cmp.getInteger(TAG_STAGE);
    stageTicks = cmp.getInteger(TAG_STAGE_TICKS);
    stage3EndTicks = cmp.getInteger(TAG_STAGE_3_END_TICKS);

    NBTTagCompound itemCmp = cmp.getCompoundTag(TAG_ITEM);
    itemToEnchant = ItemStack.loadItemStackFromNBT(itemCmp);

    enchants.clear();
    String enchStr = cmp.getString(TAG_ENCHANTS);
    if(!enchStr.isEmpty()) {
      String[] enchTokens = enchStr.split(",");
      for(String token : enchTokens) {
        String[] entryTokens = token.split(":");
        int id = Integer.parseInt(entryTokens[0]);
        int lvl = Integer.parseInt(entryTokens[1]);
        enchants.add(new EnchantmentData(id, lvl));
      }
    }
  }

  private boolean hasEnchantAlready(int enchant) {
    for(EnchantmentData data : enchants)
      if(data.enchant == enchant)
        return true;

    return false;
  }

  public boolean isEnchantmentValid(short id) {
    Enchantment ench = Enchantment.enchantmentsList[id];
    if(!ench.canApply(itemToEnchant) || !ench.type.canEnchantItem(itemToEnchant.getItem()))
      return false;

    for(EnchantmentData data : enchants) {
      Enchantment otherEnch = Enchantment.enchantmentsList[data.enchant];
      if(!otherEnch.canApplyTogether(ench) || !ench.canApplyTogether(otherEnch))
        return false;
    }

    return true;
  }

  public static boolean canEnchanterExist(World world, int x, int y, int z, int meta) {
    for(int[] obsidian : OBSIDIAN_LOCATIONS)
      if(world.getBlock(obsidian[0] + x, obsidian[1] + y, obsidian[2] + z) != Blocks.obsidian)
        return false;

    for(int[] pylon : PYLON_LOCATIONS[meta])
      if(world.getBlock(pylon[0] + x, pylon[1] + y, pylon[2] + z) != ModBlocks.pylon ||
      world.getBlock(pylon[0] + x, pylon[1] + y - 1, pylon[2] + z) != ModBlocks.flower && world.getBlock(pylon[0] + x, pylon[1] + y - 1, pylon[2] + z) != ModBlocks.shinyFlower)
        return false;

    for(int[] flower : FLOWER_LOCATIONS) {
      Block block = world.getBlock(flower[0] + x, flower[1] + y, flower[2] + z);
      if(block != ModBlocks.flower && block != ModBlocks.shinyFlower)
        return false;
    }


    return true;
  }

  private static class EnchantmentData {

    public int enchant, level;

    public EnchantmentData(int enchant, int level) {
      this.enchant = enchant;
      this.level = level;
    }
  }

  @Override
  public boolean canAttachSpark(ItemStack stack) {
    return true;
  }

  @Override
  public void attachSpark(ISparkEntity entity) {
    // NO-OP
  }

  @Override
  public ISparkEntity getAttachedSpark() {
    List<ISparkEntity> sparks = worldObj.getEntitiesWithinAABB(ISparkEntity.class, AxisAlignedBB.getBoundingBox(xCoord, yCoord + 1, zCoord, xCoord + 1, yCoord + 2, zCoord + 1));
    if(sparks.size() == 1) {
      Entity e = (Entity) sparks.get(0);
      return (ISparkEntity) e;
    }

    return null;
  }

  @Override
  public boolean areIncomingTranfersDone() {
    return stage == 3;
  }

}
TOP

Related Classes of vazkii.botania.common.block.tile.TileEnchanter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.