/**
* Copyright (c) Lambda Innovation, 2013-2016
* This file is part of the AcademyCraft mod.
* https://github.com/LambdaInnovation/AcademyCraft
* Licensed under GPLv3, see project root for more information.
*/
package cn.academy.energy.block.wind;
import cn.academy.core.tile.TileInventory;
import cn.academy.energy.ModuleEnergy;
import cn.academy.energy.client.render.block.RenderWindGenMain;
import cn.lambdalib.annoreg.core.Registrant;
import cn.lambdalib.annoreg.mc.RegTileEntity;
import cn.lambdalib.multiblock.BlockMulti;
import cn.lambdalib.multiblock.BlockMulti.SubBlockPos;
import cn.lambdalib.multiblock.IMultiTile;
import cn.lambdalib.multiblock.InfoBlockMulti;
import cn.lambdalib.s11n.network.TargetPoints;
import cn.lambdalib.s11n.network.NetworkMessage;
import cn.lambdalib.s11n.network.NetworkMessage.Listener;
import cn.lambdalib.s11n.network.NetworkMessage.NullablePar;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.ArrayList;
import java.util.List;
/**
* @author WeAthFolD
*/
@Registrant
@RegTileEntity
@RegTileEntity.HasRender
public class TileWindGenMain extends TileInventory implements IMultiTile {
static List<SubBlockPos>[] checkAreas = new ArrayList[6];
static {
List<SubBlockPos> checkArea = new ArrayList();
for(int i = -6; i <= 6; ++i) {
for(int j = -6; j <= 6; ++j) {
if(i != 0 || j != 0)
checkArea.add(new SubBlockPos(i, j, -1));
}
}
for(int i = 2; i < 6; ++i) {
List list = (checkAreas[i] = new ArrayList());
for(SubBlockPos pos : checkArea) {
list.add(BlockMulti.rotate(pos, ForgeDirection.values()[i]));
}
}
}
// State for render
@SideOnly(Side.CLIENT)
@RegTileEntity.Render
public static RenderWindGenMain renderer;
public long lastFrame = -1;
public float lastRotation;
public boolean complete;
public boolean noObstacle;
int updateWait, updateWait2;
public TileWindGenMain() {
super("windgen_main", 1);
}
// Spin logic
public boolean isFanInstalled() {
ItemStack stack = this.getStackInSlot(0);
return stack != null && stack.getItem() == ModuleEnergy.windgenFan;
}
/**
* Unit: Degree per second
*/
@SideOnly(Side.CLIENT)
public double getSpinSpeed() {
return complete ? 60.0 : 0;
}
// InfoBlockMulti delegates
InfoBlockMulti info = new InfoBlockMulti(this);
@Override
public void updateEntity() {
super.updateEntity();
info.update();
if(info.getSubID() == 0) {
if(++updateWait == 10) {
updateWait = 0;
complete = isCompleteStructure();
noObstacle = complete && isNoObstacle();
}
if(!getWorldObj().isRemote) {
if(++updateWait2 == 20) {
updateWait2 = 0;
NetworkMessage.sendToAllAround(
TargetPoints.convert(this, 50),
this, "sync", inventory[0]
);
}
}
}
}
@Override
public void readFromNBT(NBTTagCompound tag) {
super.readFromNBT(tag);
info = new InfoBlockMulti(this, tag);
}
@Override
public void writeToNBT(NBTTagCompound tag) {
super.writeToNBT(tag);
info.save(tag);
}
@Override
public InfoBlockMulti getBlockInfo() {
return info;
}
@Override
public void setBlockInfo(InfoBlockMulti i) {
info = i;
}
@Override
public boolean isItemValidForSlot(int slot, ItemStack stack) {
return slot != 0 || (stack != null && stack.getItem() == ModuleEnergy.windgenFan);
}
@SideOnly(Side.CLIENT)
@Override
public AxisAlignedBB getRenderBoundingBox() {
return INFINITE_EXTENT_AABB;
}
public boolean isCompleteStructure() {
int[] origin = ModuleEnergy.windgenMain.getOrigin(this);
if(origin == null)
return false;
int x = origin[0], y = origin[1] - 1, z = origin[2];
int state = 1;
int pillars = 0;
for(; state < 2; --y) {
Block block = worldObj.getBlock(x, y, z);
if(state == 1) {
if(block == ModuleEnergy.windgenPillar) {
++pillars;
if(pillars > WindGenerator.MAX_PILLARS)
break;
} else if(block == ModuleEnergy.windgenBase){
state = 2;
} else {
state = 3;
}
}
}
return state == 2 && pillars >= WindGenerator.MIN_PILLARS;
}
public boolean isNoObstacle() {
int x = xCoord, y = yCoord, z = zCoord;
InfoBlockMulti info = getBlockInfo();
World world = getWorldObj();
List<SubBlockPos> arr = checkAreas[info.getDir().ordinal()];
for(SubBlockPos sbp : arr) {
if(world.getBlock(x + sbp.dx, y + sbp.dy, z + sbp.dz).getMaterial() != Material.air)
return false;
}
return true;
}
@Listener(channel="sync", side=Side.CLIENT)
private void syncStack(@NullablePar ItemStack stack) {
setInventorySlotContents(0, stack);
}
}