package zmaster587.advancedRocketry.satellite;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import zmaster587.advancedRocketry.api.AdvancedRocketryBiomes;
import zmaster587.advancedRocketry.api.satellite.SatelliteProperties;
import zmaster587.advancedRocketry.item.ItemBiomeChanger;
import zmaster587.advancedRocketry.network.PacketBiomeIDChange;
import zmaster587.advancedRocketry.util.BiomeHandler;
import zmaster587.libVulpes.api.IUniversalEnergy;
import zmaster587.libVulpes.network.PacketHandler;
import zmaster587.libVulpes.util.BlockPosition;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagIntArray;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.chunk.Chunk;
public class SatelliteBiomeChanger extends SatelliteEnergy implements IUniversalEnergy {
private int biomeId;
private int radius;
//Stores blocks to be updated
//Note: we really don't care about order, in fact, lack of order is better
private List<BlockPosition> toChangeList;
private Set<Byte> discoveredBiomes;
private static int MAX_SIZE = 1024;
public SatelliteBiomeChanger() {
radius = 4;
toChangeList = new LinkedList<BlockPosition>();
discoveredBiomes = new HashSet<Byte>();
}
public void setBiome(int biomeId) {
this.biomeId = biomeId;
}
public int getBiome() {
return biomeId;
}
public Set<Byte> discoveredBiomes() {
return discoveredBiomes;
}
public void addBiome(int biome) {
byte byteBiome = (byte)biome;
if(biome != BiomeGenBase.sky.biomeID && biome != BiomeGenBase.hell.biomeID && biome != BiomeGenBase.river.biomeID && biome != AdvancedRocketryBiomes.spaceBiome.biomeID)
discoveredBiomes.add(byteBiome);
}
@Override
public String getInfo(World world) {
return "Ready";
}
@Override
public String getName() {
return "Biome Changer";
}
@Override
public ItemStack getContollerItemStack(ItemStack satIdChip,
SatelliteProperties properties) {
ItemBiomeChanger idChipItem = (ItemBiomeChanger)satIdChip.getItem();
idChipItem.setSatellite(satIdChip, properties);
return satIdChip;
}
@Override
public boolean isAcceptableControllerItemStack(ItemStack stack) {
return stack != null && stack.getItem() instanceof ItemBiomeChanger;
}
@Override
public boolean canTick() {
return true;
}
@Override
public void tickEntity() {
//This is hacky..
World world = net.minecraftforge.common.DimensionManager.getWorld(getDimensionId());
if(world != null) {
for(int i = 0; i < 10; i++) {
if(world.getTotalWorldTime() % 1 == 0 && !toChangeList.isEmpty()) {
if(extractEnergy(10, true) ==10 ) {
extractEnergy(10, false);
BlockPosition pos = toChangeList.remove(world.rand.nextInt(toChangeList.size()));
BiomeHandler.changeBiome(world, biomeId, pos.x, pos.z);
}
else
break;
}
}
}
}
public void addBlockToList(BlockPosition pos) {
if(toChangeList.size() < MAX_SIZE)
toChangeList.add(pos);
}
@Override
public boolean performAction(EntityPlayer player, World world, int x,
int y, int z) {
if(world.isRemote)
return false;
Set<Chunk> set = new HashSet<Chunk>();
radius = 16;
MAX_SIZE = 1024;
for(int xx = -radius + x; xx < radius + x; xx++) {
for(int zz = -radius + z; zz < radius + z; zz++) {
addBlockToList(new BlockPosition(xx, 0, zz));
/*BiomeGenBase biome = world.getBiomeGenForCoords(x, z);
BiomeGenBase biomeTo = BiomeGenBase.getBiome(biomeId);
if(biome.topBlock != biomeTo.topBlock) {
int yy = world.getHeightValue(xx, zz);
if(world.getBlock(xx, yy - 1, zz) == biome.topBlock)
world.setBlock(xx, yy-1, zz, biomeTo.topBlock);
}*/
}
}
//Some kind of compiler optimization is breaking if we assign block and biome in the same loop
//Causing execution order to vary from source
/*for(int xx = -radius + x; xx < radius + x; xx++) {
for(int zz = -radius + z; zz < radius + z; zz++) {
set.add(world.getChunkFromBlockCoords(xx, zz));
byte[] biomeArr = world.getChunkFromBlockCoords(xx, zz).getBiomeArray();
biomeArr[(xx % 16)+ (zz % 16)*16] = (byte)biomeId;
}
}*/
/*for(Chunk chunk : set) {
PacketHandler.sendToNearby(new PacketBiomeIDChange(chunk, world), world.provider.dimensionId, x, y, z, 64);
}*/
return false;
}
@Override
public double failureChance() {
return 0;
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
nbt.setInteger("biomeId", biomeId);
int array[] = new int[toChangeList.size()*3];
Iterator<BlockPosition> itr = toChangeList.iterator();
for(int i = 0; i < toChangeList.size(); i+=3) {
BlockPosition pos = itr.next();
array[i] = pos.x;
array[i+1] = pos.y;
array[i+2] = pos.z;
}
nbt.setTag("posList", new NBTTagIntArray(array));
array = new int[discoveredBiomes.size()];
int i = 0;
for(byte biome : discoveredBiomes) {
array[i] = biome;
i++;
}
nbt.setTag("biomeList", new NBTTagIntArray(array));
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
biomeId = nbt.getInteger("biomeId");
int array[] = nbt.getIntArray("posList");
toChangeList.clear();
for(int i = 0; i < array.length; i +=3) {
toChangeList.add(new BlockPosition(array[i], array[i+1], array[i+2]));
}
array = nbt.getIntArray("biomeList");
discoveredBiomes.clear();
for(int i = 0; i < array.length; i ++) {
discoveredBiomes.add((byte) array[i]);
}
}
@Override
public void setEnergyStored(int amt) {
battery.setEnergyStored(amt);
}
@Override
public int extractEnergy(int amt, boolean simulate) {
if(getDimensionId() != -1) {
World world = net.minecraftforge.common.DimensionManager.getWorld(getDimensionId());
if(world != null) {
battery.acceptEnergy(energyCreated(world), false);
}
}
return battery.extractEnergy(amt, simulate);
}
@Override
public int getEnergyStored() {
if(getDimensionId() != -1) {
World world = net.minecraftforge.common.DimensionManager.getWorld(getDimensionId());
if(world != null) {
battery.acceptEnergy(energyCreated(world), false);
}
}
return battery.getEnergyStored();
}
@Override
public int getMaxEnergyStored() {
return battery.getMaxEnergyStored();
}
public void setMaxEnergyStored(int max) {
battery.setMaxEnergyStored(max);
}
@Override
public int acceptEnergy(int amt, boolean simulate) {
return battery.acceptEnergy(amt, simulate);
}
}