package micdoodle8.mods.galacticraft.core.tile;
import micdoodle8.mods.galacticraft.api.item.IPaintable;
import micdoodle8.mods.galacticraft.api.tile.IDisableableMachine;
import micdoodle8.mods.galacticraft.api.vector.BlockVec3;
import micdoodle8.mods.galacticraft.core.GalacticraftCore;
import micdoodle8.mods.galacticraft.core.blocks.BlockSpaceGlass;
import micdoodle8.mods.galacticraft.core.entities.player.GCPlayerStats;
import micdoodle8.mods.galacticraft.core.inventory.IInventoryDefaults;
import micdoodle8.mods.galacticraft.core.network.IPacketReceiver;
import micdoodle8.mods.galacticraft.core.network.PacketDynamic;
import micdoodle8.mods.galacticraft.core.util.ColorUtil;
import micdoodle8.mods.galacticraft.core.util.CompatibilityManager;
import micdoodle8.mods.galacticraft.core.util.GCCoreUtil;
import net.minecraft.block.Block;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemDye;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.relauncher.Side;
import ic2.api.item.IC2Items;
import io.netty.buffer.ByteBuf;
import java.util.*;
import biomesoplenty.api.item.BOPItems;
//import net.minecraft.item.EnumDyeColor;
public class TileEntityPainter extends TileEntity implements IDisableableMachine, IInventoryDefaults, IPacketReceiver
{
private static final int RANGE_DEFAULT = 96;
public static Map<Integer, Set<BlockVec3>> loadedTilesForDim = new HashMap<Integer, Set<BlockVec3>>();
public int range = RANGE_DEFAULT; //currently unused
public int[] glassColor = new int[]{ -1, -1, -1 }; //Size of this array must match GlassType enum
public final Set<EntityPlayer> playersUsing = new HashSet<EntityPlayer>();
private ItemStack[] containingItems = new ItemStack[2];
public int guiColor = 0xffffff;
public void takeColorFromItem(ItemStack itemStack)
{
if (itemStack == null)
{
return;
}
Item item = itemStack.getItem();
int color = -1;
if (item == Items.dye)
{
color = ItemDye.dyeColors[itemStack.getItemDamage()];
}
else if (item instanceof ItemBlock)
{
Block b = ((ItemBlock)item).getBlock();
IBlockState bs = b.getStateFromMeta(itemStack.getItemDamage());
MapColor mc = b.getMapColor(bs);
color = mc.colorValue;
}
else
{
color = tryOtherModDyes(itemStack);
}
if (color >= 0)
{
color = ColorUtil.addColorsBasic(color, this.guiColor);
this.guiColor = color;
}
}
private void applyColorToItem(ItemStack itemStack, int color, Side side, EntityPlayer player)
{
if (itemStack == null)
{
return;
}
Item item = itemStack.getItem();
if (item instanceof IPaintable)
{
//TODO e.g. flags, eggs, rockets???
}
else if (item instanceof ItemBlock)
{
color = ColorUtil.lighten(color, 0.03F);
Block b = ((ItemBlock)item).block;
int result = 0;
if (b instanceof IPaintable)
{
result = ((IPaintable) b).setColor(color, player, side);
}
if (b instanceof BlockSpaceGlass)
{
int type = ((BlockSpaceGlass)b).type.ordinal();
this.glassColor[type] = color;
if (result > 0 && side == Side.CLIENT)
{
BlockSpaceGlass.updateClientRender();
}
}
}
}
private void setGlassColors(int color1, int color2, int color3)
{
boolean changes = false;
if (this.glassColor[0] != color1)
{
changes = true;
this.glassColor[0] = color1;
}
if (this.glassColor[1] != color2)
{
changes = true;
this.glassColor[1] = color2;
}
if (this.glassColor[2] != color3)
{
changes = true;
this.glassColor[2] = color3;
}
// if (changes)
// ColorUtil.updateColorsForArea(this.worldObj), this.pos, this.range, this.glassColor[0], this.glassColor[1], this.glassColor[2]);;
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
if (nbt.hasKey("guic"))
{
this.glassColor[0] = nbt.getInteger("G1");
this.glassColor[1] = nbt.getInteger("G2");
this.glassColor[2] = nbt.getInteger("G3");
this.range = nbt.getInteger("rge");
this.guiColor = nbt.getInteger("guic");
}
final NBTTagList tagList = nbt.getTagList("Items", 10);
this.containingItems = new ItemStack[this.getSizeInventory()];
for (int i = 0; i < tagList.tagCount(); ++i)
{
final NBTTagCompound tag = tagList.getCompoundTagAt(i);
final int slot = tag.getByte("Slot") & 255;
if (slot < this.containingItems.length)
{
this.containingItems[slot] = ItemStack.loadItemStackFromNBT(tag);
}
}
}
@Override
public void writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
nbt.setInteger("G1", this.glassColor[0]);
nbt.setInteger("G2", this.glassColor[1]);
nbt.setInteger("G3", this.glassColor[2]);
nbt.setInteger("guic", this.guiColor);
nbt.setInteger("rge", this.range);
final NBTTagList tagList = new NBTTagList();
for (int i = 0; i < this.containingItems.length; ++i)
{
if (this.containingItems[i] != null)
{
final NBTTagCompound tag = new NBTTagCompound();
tag.setByte("Slot", (byte) i);
this.containingItems[i].writeToNBT(tag);
tagList.appendTag(tag);
}
}
nbt.setTag("Items", tagList);
}
private static Set<BlockVec3> getLoadedTiles(World world)
{
int dimID = GCCoreUtil.getDimensionID(world);
Set<BlockVec3> loaded = loadedTilesForDim.get(dimID);
if (loaded == null)
{
loaded = new HashSet<BlockVec3>();
loadedTilesForDim.put(dimID, loaded);
}
return loaded;
}
@Override
public void onLoad()
{
if (this.worldObj.isRemote)
{
//Request any networked information from server on first client update
GalacticraftCore.packetPipeline.sendToServer(new PacketDynamic(this));
}
else
{
this.getLoadedTiles(this.worldObj).add(new BlockVec3(this.pos));
}
}
@Override
public void onChunkUnload()
{
this.getLoadedTiles(this.worldObj).remove(new BlockVec3(this.pos));
super.onChunkUnload();
}
@Override
public void invalidate()
{
if (!this.worldObj.isRemote)
this.getLoadedTiles(this.worldObj).remove(new BlockVec3(this.pos));
super.invalidate();
}
public static void onServerTick(World world)
{
Set<BlockVec3> loaded = getLoadedTiles(world);
int dimID = GCCoreUtil.getDimensionID(world);
List<EntityPlayerMP> allPlayers = (List<EntityPlayerMP>)FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().playerEntityList;
for (final EntityPlayerMP player : allPlayers)
{
if (player.dimension != dimID) continue;
BlockVec3 playerPos = new BlockVec3(player);
BlockVec3 nearest = null;
int shortestDistance = RANGE_DEFAULT * RANGE_DEFAULT;
for (final BlockVec3 bv : loaded)
{
int distance = bv.distanceSquared(playerPos);
if (distance < shortestDistance)
{
shortestDistance = distance;
nearest = bv;
}
}
if (nearest != null)
{
TileEntity te = nearest.getTileEntity(world);
if (te instanceof TileEntityPainter)
{
((TileEntityPainter)te).dominantToPlayer(player);
}
}
//TODO
//Make sure this works in a way so that the nearest Painter quickly takes priority, but there is no race condition...
//Also maybe some hysteresis?
}
}
private void dominantToPlayer(EntityPlayerMP player)
{
GCPlayerStats.get(player).setGlassColors(this.glassColor[0], this.glassColor[1], this.glassColor[2]);
}
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate)
{
return oldState.getBlock() != newSate.getBlock();
}
@Override
public String getName()
{
return GCCoreUtil.translate("tile.machine3.9.name");
}
@Override
public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
{
return this.worldObj.getTileEntity(this.getPos()) == this && par1EntityPlayer.getDistanceSq(this.getPos().getX() + 0.5D, this.getPos().getY() + 0.5D, this.getPos().getZ() + 0.5D) <= 64.0D;
}
@Override
public void setDisabled(int index, boolean disabled)
{
//Used to do the painting!
for (EntityPlayer entityPlayer : playersUsing)
{
this.buttonPressed(index, entityPlayer, Side.SERVER);
}
}
public void buttonPressed(int index, EntityPlayer player, Side side)
{
switch (index)
{
case 0: //Apply Paint
this.applyColorToItem(this.getStackInSlot(1), this.guiColor, side, player);
break;
case 1: //Mix Colors
this.takeColorFromItem(this.getStackInSlot(0));
break;
case 2: //Reset Colors
this.guiColor = 0xffffff;
break;
}
}
@Override
public boolean getDisabled(int index)
{
return false;
}
@Override
public int getSizeInventory()
{
return 2;
}
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{
return false;
}
@Override
public ItemStack getStackInSlot(int par1)
{
return this.containingItems[par1];
}
@Override
public ItemStack decrStackSize(int par1, int par2)
{
if (containingItems[par1] != null)
{
ItemStack var3;
if (containingItems[par1].stackSize <= par2)
{
var3 = containingItems[par1];
containingItems[par1] = null;
this.markDirty();
return var3;
}
else
{
var3 = containingItems[par1].splitStack(par2);
if (containingItems[par1].stackSize == 0)
{
containingItems[par1] = null;
}
this.markDirty();
return var3;
}
}
else
{
return null;
}
}
@Override
public ItemStack removeStackFromSlot(int par1)
{
if (containingItems[par1] != null)
{
final ItemStack var2 = containingItems[par1];
containingItems[par1] = null;
this.markDirty();
return var2;
}
else
{
return null;
}
}
@Override
public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
{
containingItems[par1] = par2ItemStack;
if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit())
{
par2ItemStack.stackSize = this.getInventoryStackLimit();
}
this.markDirty();
}
@Override
public int getInventoryStackLimit()
{
return 64;
}
@Override
public void getNetworkedData(ArrayList<Object> sendData)
{
if (this.worldObj.isRemote)
{
return;
}
sendData.add(this.guiColor);
}
@Override
public void decodePacketdata(ByteBuf buffer)
{
if (this.worldObj.isRemote)
{
try
{
this.guiColor = buffer.readInt();
}
catch (Exception ignore)
{
ignore.printStackTrace();
}
}
}
//Any special cases go here, e.g. coloured dye or paint items added by other mods
private static int tryOtherModDyes(ItemStack itemStack)
{
Item item = itemStack.getItem();
if (CompatibilityManager.isIc2Loaded())
{
ItemStack ic2paintbrush = IC2Items.getItem("painter");
if (ic2paintbrush != null && item == ic2paintbrush.getItem())
{
return ItemDye.dyeColors[itemStack.getItemDamage()];
}
}
if (CompatibilityManager.isBOPLoaded())
{
if (item == BOPItems.black_dye) return ItemDye.dyeColors[EnumDyeColor.BLACK.getDyeDamage()];
if (item == BOPItems.blue_dye) return ItemDye.dyeColors[EnumDyeColor.BLUE.getDyeDamage()];
if (item == BOPItems.brown_dye) return ItemDye.dyeColors[EnumDyeColor.BROWN.getDyeDamage()];
if (item == BOPItems.green_dye) return ItemDye.dyeColors[EnumDyeColor.GREEN.getDyeDamage()];
if (item == BOPItems.white_dye) return ItemDye.dyeColors[EnumDyeColor.WHITE.getDyeDamage()];
}
return -1;
}
}