/**
* 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 the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Sep 6, 2015, 3:46:10 PM (GMT)]
*/
package vazkii.botania.common.block.subtile.generating;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import vazkii.botania.api.lexicon.LexiconEntry;
import vazkii.botania.api.subtile.RadiusDescriptor;
import vazkii.botania.api.subtile.SubTileGenerating;
import vazkii.botania.common.block.ModBlocks;
import vazkii.botania.common.block.tile.TileCell;
import vazkii.botania.common.lexicon.LexiconData;
public class SubTileDandelifeon extends SubTileGenerating {
private static final int RANGE = 12;
private static final int SPEED = 10;
// private static final int MAX_GENERATIONS = 100;
private static final int MAX_MANA_GENERATIONS = 100;
private static final int MANA_PER_GEN = 60;
private static final int[][] ADJACENT_BLOCKS = new int[][] {
{ -1, -1 },
{ -1, +0 },
{ -1, +1 },
{ +0, +1 },
{ +1, +1 },
{ +1, +0 },
{ +1, -1 },
{ +0, -1 }
};
@Override
public void onUpdate() {
super.onUpdate();
if(!supertile.getWorld().isRemote && redstoneSignal > 0 && ticksExisted % SPEED == 0)
runSimulation();
}
void runSimulation() {
int[][] table = getCellTable();
List<int[]> changes = new ArrayList<>();
new ArrayList();
boolean wipe = false;
for(int i = 0; i < table.length; i++)
for(int j = 0; j < table[0].length; j++) {
int gen = table[i][j];
int adj = getAdjCells(table, i, j);
int newVal = gen;
if(adj < 2 || adj > 3)
newVal = -1;
else {
if(adj == 3 && gen == -1)
newVal = getSpawnCellGeneration(table, i, j);
else if(gen > -1)
newVal = gen + 1;
}
int xdist = Math.abs(i - RANGE);
int zdist = Math.abs(j - RANGE);
int allowDist = 1;
if(xdist <= allowDist && zdist <= allowDist && newVal > -1) {
gen = newVal;
newVal = gen == 1 ? -1 : -2;
}
if(newVal != gen) {
changes.add(new int[] { i, j, newVal, gen });
if(newVal == -2)
wipe = true;
}
}
BlockPos pos = supertile.getPos();
for(int[] change : changes) {
BlockPos pos_ = pos.add(-RANGE + change[0], 0, -RANGE + change[1]);
int val = change[2];
if(val != -2 && wipe)
val = -1;
int old = change[3];
setBlockForGeneration(pos_, val, old);
}
}
int[][] getCellTable() {
int diam = RANGE * 2 + 1;
int[][] table = new int[diam][diam];
BlockPos pos = supertile.getPos();
for(int i = 0; i < diam; i++)
for(int j = 0; j < diam; j++) {
BlockPos pos_ = pos.add(-RANGE + i, 0, -RANGE + j);
table[i][j] = getCellGeneration(pos_);
}
return table;
}
int getCellGeneration(BlockPos pos) {
TileEntity tile = supertile.getWorld().getTileEntity(pos);
if(tile instanceof TileCell)
return ((TileCell) tile).isSameFlower(supertile) ? ((TileCell) tile).getGeneration() : 0;
return -1;
}
int getAdjCells(int[][] table, int x, int z) {
int count = 0;
for(int[] shift : ADJACENT_BLOCKS) {
int xp = x + shift[0];
int zp = z + shift[1];
if(!isOffBounds(table, xp, zp)) {
int gen = table[xp][zp];
if(gen >= 0)
count++;
}
}
return count;
}
int getSpawnCellGeneration(int[][] table, int x, int z) {
int max = -1;
for(int[] shift : ADJACENT_BLOCKS) {
int xp = x + shift[0];
int zp = z + shift[1];
if(!isOffBounds(table, xp, zp)) {
int gen = table[xp][zp];
if(gen > max)
max = gen;
}
}
return max == -1 ? -1 : max + 1;
}
boolean isOffBounds(int[][] table, int x, int z) {
return x < 0 || z < 0 || x >= table.length || z >= table[0].length;
}
void setBlockForGeneration(BlockPos pos, int gen, int prevGen) {
World world = supertile.getWorld();
IBlockState stateAt = world.getBlockState(pos);
Block blockAt = stateAt.getBlock();
TileEntity tile = world.getTileEntity(pos);
if(gen == -2) {
int val = Math.min(MAX_MANA_GENERATIONS, prevGen) * MANA_PER_GEN;
mana = Math.min(getMaxMana(), mana + val);
//world.setBlockToAir(x, y, z);
} else if(blockAt == ModBlocks.cellBlock) {
if(gen < 0)
world.setBlockToAir(pos);
else ((TileCell) tile).setGeneration(supertile, gen);
} else if(gen >= 0 && blockAt.isAir(stateAt, supertile.getWorld(), pos)) {
world.setBlockState(pos, ModBlocks.cellBlock.getDefaultState());
tile = world.getTileEntity(pos);
((TileCell) tile).setGeneration(supertile, gen);
}
}
@Override
public boolean acceptsRedstone() {
return true;
}
@Override
public RadiusDescriptor getRadius() {
return new RadiusDescriptor.Square(toBlockPos(), RANGE);
}
@Override
public int getMaxMana() {
return 50000;
}
@Override
public int getColor() {
return 0x9c0a7e;
}
@Override
public LexiconEntry getEntry() {
return LexiconData.dandelifeon;
}
}