/*
* This file is part of Matter Overdrive
* Copyright (c) 2015., Simeon Radivoev, All rights reserved.
*
* Matter Overdrive is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Matter Overdrive is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Matter Overdrive. If not, see <http://www.gnu.org/licenses>.
*/
package matteroverdrive.items;
import com.mojang.realmsclient.gui.ChatFormatting;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import matteroverdrive.MatterOverdrive;
import matteroverdrive.Reference;
import matteroverdrive.api.IScannable;
import matteroverdrive.api.events.MOEventScan;
import matteroverdrive.api.inventory.IBlockScanner;
import matteroverdrive.api.matter.IMatterDatabase;
import matteroverdrive.client.sound.MachineSound;
import matteroverdrive.data.BlockPos;
import matteroverdrive.data.ItemPattern;
import matteroverdrive.gui.GuiMatterScanner;
import matteroverdrive.handler.KeyHandler;
import matteroverdrive.handler.SoundHandler;
import matteroverdrive.items.includes.MOBaseItem;
import matteroverdrive.proxy.ClientProxy;
import matteroverdrive.util.MOPhysicsHelper;
import matteroverdrive.util.MOStringHelper;
import matteroverdrive.util.MatterDatabaseHelper;
import matteroverdrive.util.MatterHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.*;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import org.apache.logging.log4j.Level;
import org.lwjgl.input.Keyboard;
import java.util.List;
public class MatterScanner extends MOBaseItem implements IBlockScanner
{
public static final String SELECTED_TAG_NAME = "lastSelected";
public static final String PAGE_TAG_NAME = "page";
public static final String PANEL_OPEN_TAG_NAME = "panelOpen";
public static final int PROGRESS_PER_ITEM = 10;
public static final int SCAN_TIME = 60;
@SideOnly(Side.CLIENT)
public static MachineSound scanningSound;
public static IIcon offline_icon;
public MatterScanner(String name)
{
super(name);
}
/**
* Returns the holoIcon index of the stack given as argument.
*/
@Override
@SideOnly(Side.CLIENT)
public IIcon getIconIndex(ItemStack itemStack)
{
if (itemStack.hasTagCompound() && Minecraft.getMinecraft().theWorld != null)
{
if (isLinked(itemStack))
return this.itemIcon;
}
return offline_icon;
}
@Override
public void addInformation(ItemStack itemstack, EntityPlayer player, List infos, boolean p_77624_4_)
{
if(hasDetails(itemstack))
{
if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT))
{
addDetails(itemstack,player,infos);
}
else
{
infos.add(MOStringHelper.MORE_INFO);
infos.add("Press '"+ EnumChatFormatting.YELLOW + GameSettings.getKeyDisplayString(ClientProxy.keyHandler.getBinding(KeyHandler.MATTER_SCANNER_KEY).getKeyCode()) + EnumChatFormatting.GRAY + "' to open GUI");
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void registerIcons(IIconRegister iconRegister)
{
this.itemIcon = iconRegister.registerIcon(this.getIconString());
offline_icon = iconRegister.registerIcon(Reference.MOD_ID + ":" + "matter_scanner_offline");
}
@Override
public void addDetails(ItemStack itemstack, EntityPlayer player, List infos)
{
if (isLinked(itemstack))
{
if (itemstack.hasTagCompound()) {
infos.add(ChatFormatting.GREEN + "Online");
}
ItemPattern lastSelected = getSelectedAsPattern(itemstack);
if(lastSelected != null) {
infos.add("Progress: " + lastSelected.getProgress() + " / " + 100 + " %");
infos.add("Selected: " + lastSelected.getDisplayName());
}
} else {
infos.add(ChatFormatting.RED + "Offline");
}
}
@Override
public boolean hasDetails(ItemStack itemStack)
{
return true;
}
public static IMatterDatabase getLink(World world,ItemStack scanner)
{
if(scanner != null && scanner.getItem() instanceof MatterScanner)
{
if(scanner.hasTagCompound())
{
if(scanner.getTagCompound().getBoolean("isLinked"))
{
int x = scanner.getTagCompound().getInteger("link_x");
int y = scanner.getTagCompound().getInteger("link_y");
int z = scanner.getTagCompound().getInteger("link_z");
TileEntity e = world.getTileEntity(x, y, z);
if (e instanceof IMatterDatabase)
return (IMatterDatabase) e;
}
}
}
return null;
}
public static BlockPos getLinkPosition(ItemStack scanner)
{
if(scanner != null && scanner.getItem() instanceof MatterScanner) {
if (scanner.hasTagCompound())
{
return new BlockPos(scanner.getTagCompound().getInteger("link_x"), scanner.getTagCompound().getInteger("link_y"), scanner.getTagCompound().getInteger("link_z"));
}
}
return new BlockPos(0, 0, 0);
}
public static boolean isLinked(ItemStack scanner)
{
if(scanner != null && scanner.getItem() instanceof MatterScanner) {
if (scanner.hasTagCompound()) {
return scanner.getTagCompound().getBoolean("isLinked");
}
}
return false;
}
public static void unLink(World world,ItemStack scanner)
{
if(scanner.hasTagCompound())
{
scanner.getTagCompound().setBoolean("isLinked", false);
}
}
public static void link(World world, int xCoord, int yCoord, int zCoord,ItemStack scanner)
{
if(scanner.getItem() instanceof MatterScanner)
{
((MatterScanner)scanner.getItem()).TagCompountCheck(scanner);
}
if(scanner.hasTagCompound())
{
scanner.getTagCompound().setBoolean("isLinked",true);
scanner.getTagCompound().setInteger("link_x", xCoord);
scanner.getTagCompound().setInteger("link_y", yCoord);
scanner.getTagCompound().setInteger("link_z", zCoord);
}
}
public int getItemStackLimit(ItemStack item)
{
return 1;
}
private void resetScanProgress(ItemStack item)
{
if(item.hasTagCompound())
{
item.getTagCompound().setInteger(MatterDatabaseHelper.PROGRESS_TAG_NAME,0);
}
}
private boolean HarvestBlock(ItemStack scanner,EntityPlayer player,World world,int x,int y,int z)
{
if(!world.isRemote)
{
ItemStack item = MatterDatabaseHelper.GetItemStackFromWorld(world, x, y, z);
return world.func_147480_a(x, y, z, false);
}
return false;
}
public static void setSelected(World world,ItemStack scanner,ItemStack itemStack)
{
if(scanner.hasTagCompound())
{
ItemPattern itemPattern = getSelectedFromDatabase(world,scanner,itemStack);
if (itemPattern == null)
{
itemPattern = new ItemPattern(itemStack);
}
setSelected(scanner, itemPattern);
}
}
public static void setSelected(ItemStack scanner,ItemPattern itemPattern)
{
if(scanner.hasTagCompound())
{
NBTTagCompound seletedNBT = new NBTTagCompound();
itemPattern.writeToNBT(seletedNBT);
scanner.getTagCompound().setTag(SELECTED_TAG_NAME, seletedNBT);
}
}
public static ItemPattern getSelectedAsPattern(ItemStack scanner)
{
if(scanner.hasTagCompound() && scanner.getTagCompound().hasKey(SELECTED_TAG_NAME))
{
return new ItemPattern(scanner.getTagCompound().getCompoundTag(SELECTED_TAG_NAME));
}
return null;
}
public static ItemStack getSelectedAsItem(ItemStack scanner)
{
if(scanner.hasTagCompound())
{
return ItemStack.loadItemStackFromNBT(scanner.getTagCompound().getCompoundTag(SELECTED_TAG_NAME));
}
return null;
}
public static ItemPattern getSelectedFromDatabase(World world,ItemStack scanner,ItemStack forItem)
{
IMatterDatabase database = getLink(world,scanner);
if (database != null)
{
return database.getPattern(forItem);
}
return null;
}
@Override
public void InitTagCompount(ItemStack stack)
{
MatterDatabaseHelper.initTagCompound(stack);
}
@SideOnly(Side.CLIENT)
public static void DisplayGuiScreen()
{
try {
if (MatterHelper.isMatterScanner(Minecraft.getMinecraft().thePlayer.getHeldItem())) {
Minecraft.getMinecraft().displayGuiScreen(new GuiMatterScanner(Minecraft.getMinecraft().thePlayer.getHeldItem(), Minecraft.getMinecraft().thePlayer.inventory.currentItem));
return;
}
for (int i = 0; i < Minecraft.getMinecraft().thePlayer.inventory.getSizeInventory(); i++) {
if (MatterHelper.isMatterScanner(Minecraft.getMinecraft().thePlayer.inventory.getStackInSlot(i))) {
Minecraft.getMinecraft().displayGuiScreen(new GuiMatterScanner(Minecraft.getMinecraft().thePlayer.inventory.getStackInSlot(i), i));
return;
}
}
}catch (Exception e)
{
MatterOverdrive.log.log(Level.ERROR,e,"There was a problem while trying to open Matter Scanner GUI");
}
}
public static int getLastPage(ItemStack scanner)
{
if(scanner.hasTagCompound())
{
return scanner.getTagCompound().getShort(PAGE_TAG_NAME);
}
return 0;
}
/**
* returns the action that specifies what animation to play when the items is being used
*/
public EnumAction getItemUseAction(ItemStack p_77661_1_)
{
return EnumAction.block;
}
/**
* How long it takes to use or consume an item
*/
public int getMaxItemUseDuration(ItemStack scanner)
{
ItemStack selected = getSelectedAsItem(scanner);
if (selected != null)
{
if (MatterHelper.CanScan(selected))
{
return SCAN_TIME + MatterHelper.getMatterAmountFromItem(selected);
}
}
return Integer.MAX_VALUE;
}
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
{
MovingObjectPosition hit = getScanningPos(itemstack,entityplayer);
if( hit != null && hit.typeOfHit != MovingObjectPosition.MovingObjectType.MISS)
{
if (world.isRemote)
playSound(entityplayer.posX, entityplayer.posY, entityplayer.posZ);
entityplayer.setItemInUse(itemstack, getMaxItemUseDuration(itemstack));
}
return itemstack;
}
@Override
public void onUpdate(ItemStack itemStack,World world, Entity entity, int p_77663_4_, boolean p_77663_5_)
{
super.onUpdate(itemStack,world,entity,p_77663_4_,p_77663_5_);
if (world.isRemote) {
if (entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entity;
if (player.isUsingItem())
{
} else
{
stopScanSounds();
}
}
}
}
public ItemStack onEaten(ItemStack scanner, World world, EntityPlayer player)
{
if(world.isRemote)
{
stopScanSounds();
return scanner;
}
MovingObjectPosition position = getScanningPos(scanner,player);
if (position != null && position.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
if (!world.isRemote) {
int x = position.blockX;
int y = position.blockY;
int z = position.blockZ;
ItemStack worldItem = MatterDatabaseHelper.GetItemStackFromWorld(world, x, y, z);
//finished scanning
if (!MinecraftForge.EVENT_BUS.post(new MOEventScan(player,scanner,position)))
{
Scan(world, scanner, player, worldItem, x, y, z);
}
}
}
return scanner;
}
@Override
public MovingObjectPosition getScanningPos(ItemStack itemStack,EntityPlayer player)
{
return MOPhysicsHelper.rayTrace(player, player.worldObj, 5, 0, Vec3.createVectorHelper(0, player.worldObj.isRemote ? 0 : player.getEyeHeight(), 0), true, false);
}
@Override
public boolean destroysBlocks(ItemStack itemStack)
{
return true;
}
@Override
public void onUsingTick(ItemStack scanner, EntityPlayer player, int count)
{
MovingObjectPosition hit = getScanningPos(scanner,player);
if (hit != null) {
if (hit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
int x = hit.blockX;
int y = hit.blockY;
int z = hit.blockZ;
ItemStack lastSelected = getSelectedAsItem(scanner);
ItemStack worldItem = MatterDatabaseHelper.GetItemStackFromWorld(player.worldObj, x, y, z);
if (!MatterDatabaseHelper.areEqual(lastSelected, worldItem)) {
setSelected(player.worldObj,scanner, worldItem);
player.stopUsingItem();
if (player.worldObj.isRemote) {
stopScanSounds();
}
}
}
}
else
{
if (player.worldObj.isRemote)
{
stopScanSounds();
player.stopUsingItem();
}
}
}
@SideOnly(Side.CLIENT)
private void playSound(double x,double y,double z)
{
if(scanningSound == null)
{
scanningSound = new MachineSound(new ResourceLocation(Reference.MOD_ID + ":" +"scanner_scanning"),(float)x,(float)y,(float)z,0.6f,1);
Minecraft.getMinecraft().getSoundHandler().playSound(scanningSound);
}
}
public void onPlayerStoppedUsing(ItemStack scanner, World world, EntityPlayer player, int count)
{
if (world.isRemote)
stopScanSounds();
}
@SideOnly(Side.CLIENT)
private void stopScanSounds()
{
if(scanningSound != null)
{
scanningSound.stopPlaying();
scanningSound = null;
}
}
public boolean Scan(World world,ItemStack scanner,EntityPlayer player,ItemStack worldBlock,int x,int y,int z)
{
this.TagCompountCheck(scanner);
StringBuilder scanInfo = new StringBuilder();
IMatterDatabase database = getLink(world, scanner);
if (database != null && MatterHelper.CanScan(worldBlock))
{
resetScanProgress(scanner);
scanInfo.append(EnumChatFormatting.YELLOW + "[" + scanner.getDisplayName() + "] ");
if (database.addItem(worldBlock, PROGRESS_PER_ITEM,false,scanInfo)) {
//scan successful
SoundHandler.PlaySoundAt(world, "scanner_success", player);
DisplayInfo(player, scanInfo, EnumChatFormatting.GREEN);
return HarvestBlock(scanner, player, world, x, y, z);
}
else
{
//scan fail
DisplayInfo(player, scanInfo, EnumChatFormatting.RED);
SoundHandler.PlaySoundAt(world, "scanner_fail", player);
return false;
}
}else
{
if (world.getBlock(x,y,z) instanceof IScannable)
{
((IScannable) world.getBlock(x,y,z)).onScan(world,x,y,z,player,scanner);
//DisplayInfo(player, scanInfo, EnumChatFormatting.GREEN);
return true;
}else if (world.getTileEntity(x,y,z) instanceof IScannable)
{
((IScannable) world.getBlock(x,y,z)).onScan(world,x,y,z,player,scanner);
return true;
}
}
return false;
}
private void DisplayInfo(EntityPlayer player,StringBuilder scanInfo,EnumChatFormatting formatting)
{
if (player != null && !scanInfo.toString().isEmpty())
{
player.addChatMessage(new ChatComponentText(formatting + scanInfo.toString()));
}
}
}