package micdoodle8.mods.galacticraft.planets.asteroids.world.gen.base;
import micdoodle8.mods.galacticraft.core.GCBlocks;
import micdoodle8.mods.galacticraft.core.GCItems;
import micdoodle8.mods.galacticraft.core.blocks.BlockMulti;
import micdoodle8.mods.galacticraft.core.entities.EntityHangingSchematic;
import micdoodle8.mods.galacticraft.core.items.ItemCanisterGeneric;
import micdoodle8.mods.galacticraft.core.tile.IMultiBlock;
import micdoodle8.mods.galacticraft.core.tile.TileEntityCargoLoader;
import micdoodle8.mods.galacticraft.core.tile.TileEntityCrafting;
import micdoodle8.mods.galacticraft.core.tile.TileEntityEnergyStorageModule;
import micdoodle8.mods.galacticraft.core.tile.TileEntityFluidTank;
import micdoodle8.mods.galacticraft.planets.asteroids.blocks.AsteroidBlocks;
import micdoodle8.mods.galacticraft.planets.asteroids.world.gen.base.BaseDeck.EnumBaseType;
import micdoodle8.mods.galacticraft.planets.mars.MarsModule;
import micdoodle8.mods.galacticraft.planets.mars.blocks.BlockMachineMars;
import micdoodle8.mods.galacticraft.planets.mars.blocks.MarsBlocks;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityBrewingStand;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraftforge.fluids.FluidStack;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
public class BaseRoom extends SizedPiece
{
private EnumRoomType type;
private boolean nearEnd;
private boolean farEnd;
private int deckTier;
//Temporary treasure items until we have a specific Asteroids treasure
private static final ItemStack TREASURE1 = new ItemStack(Items.ghast_tear, 2, 0);
private static final ItemStack TREASURE2 = new ItemStack(Items.nether_star, 1, 0);
public BaseRoom()
{
}
public BaseRoom(BaseConfiguration configuration, Random rand, int blockPosX, int yPos, int blockPosZ, int sizeX, int sizeY, int sizeZ, EnumFacing entranceDir, EnumRoomType roomType, boolean near, boolean far, int deckTier)
{
super(configuration, sizeX, sizeY, sizeZ, entranceDir.getOpposite());
this.coordBaseMode = this.direction;
this.type = roomType;
this.nearEnd = near;
this.farEnd = far;
this.deckTier = deckTier;
this.boundingBox = new StructureBoundingBox(blockPosX, yPos, blockPosZ, blockPosX + this.sizeX, yPos + this.sizeY, blockPosZ + this.sizeZ);
}
@Override
protected void writeStructureToNBT(NBTTagCompound tagCompound)
{
super.writeStructureToNBT(tagCompound);
int details = this.deckTier + (this.nearEnd ? 16 : 0) + (this.farEnd ? 32 : 0);
tagCompound.setInteger("brT", type.ordinal());
tagCompound.setInteger("brD", details);
}
@Override
protected void readStructureFromNBT(NBTTagCompound tagCompound)
{
super.readStructureFromNBT(tagCompound);
try
{
int typeNo = tagCompound.getInteger("brT");
if (typeNo < EnumRoomType.values().length)
{
this.type = EnumRoomType.values()[typeNo];
}
else
this.type = EnumRoomType.EMPTY;
int details = tagCompound.getInteger("brD");
this.deckTier = details & 15;
this.nearEnd = (details & 16) == 16;
this.farEnd = (details & 32) == 32;
}
catch (Exception e)
{
System.err.println("Failed to read Abandoned Base configuration from NBT");
System.err.println(tagCompound.toString());
}
}
@Override
public boolean addComponentParts(World worldIn, Random random, StructureBoundingBox chunkBoundary)
{
IBlockState blockAir = Blocks.air.getDefaultState();
Block blockStair = GCBlocks.moonStoneStairs;
boolean axisEW = getDirection().getAxis() == EnumFacing.Axis.X;
int maxX = axisEW ? this.sizeZ : this.sizeX;
int maxZ = axisEW ? this.sizeX : this.sizeZ;
int randomInt = random.nextInt(99);
for (int xx = 0; xx <= maxX; xx++)
{
boolean near = this.nearEnd && xx == maxX;
boolean far = this.farEnd && xx == 0;
for (int yy = 0; yy <= this.sizeY; yy++)
{
for (int zz = 0; zz <= maxZ; zz++)
{
//5 outer walls of the room
if (xx == 0 || xx == maxX || yy == 0 || yy == this.sizeY || zz == maxZ)
{
boolean xEntrance = maxX > 6 ? (xx > 2 && xx < maxX - 2) : (xx > 1 && xx < maxX - 1);
if (this.type.blockEntrance != null && yy == 0 && zz == 0 && xEntrance && this.configuration.getDeckType() != EnumBaseType.TUNNELER)
{
this.setBlockState(worldIn, this.type.blockEntrance, xx, yy, zz, chunkBoundary);
this.setBlockState(worldIn, this.configuration.getWallBlock(), xx, yy - 1, zz, chunkBoundary);
}
//Shave the top and bottom corners
else if (!((zz == maxZ || near || far) && (yy == 0 && (this.deckTier & 1) == 1 || yy == this.sizeY && (this.deckTier & 2) == 2 || (zz == maxZ && (near || far)))) || zz == 0 && yy == 0)
{
this.setBlockState(worldIn, this.configuration.getWallBlock(), xx, yy, zz, chunkBoundary);
}
//Special case, fill in some corners on hangardeck top deck
else if (yy == this.sizeY && (this.deckTier & 2) == 2 && this.configuration.isHangarDeck() && zz < 3)
{
if (xx == 0 || xx == maxX)
{
this.setBlockState(worldIn, this.configuration.getWallBlock(), xx, yy, zz, chunkBoundary);
}
}
}
else
{
//Room internals
if ((xx > 1 && xx < maxX - 1) && (zz > 0 && zz < maxZ - 1) || (yy > 1 && yy < this.sizeY - 1) || this.type.doEntryWallsToo)
{
BlockPos blockpos = new BlockPos(this.getXWithOffset(xx, zz), this.getYWithOffset(yy), this.getZWithOffset(xx, zz));
if (chunkBoundary.isVecInside(blockpos))
{
this.buildRoomContents(worldIn, xx, yy, zz, maxX - 1, maxZ - 1, blockpos, randomInt);
}
}
else if (this.configuration.getDeckType() == EnumBaseType.TUNNELER && (yy == 1 || yy == this.sizeY - 1))
{
int meta = 1;
if (xx == 1) meta = 3;
else if (xx == maxX - 1) meta = 2;
else if (zz == 0) meta = 0;
if (this.direction == EnumFacing.NORTH)
{
meta ^= 3 ^ meta / 2;
}
else if (this.direction == EnumFacing.SOUTH)
{
meta ^= 2 + meta / 2;
}
else if (this.direction == EnumFacing.EAST)
meta ^= 1;
meta += (yy == 1) ? 0 : 4;
this.setBlockState(worldIn, blockStair.getStateFromMeta(meta), xx, yy, zz, chunkBoundary);
}
else if (yy == 1 && this.type.blockFloor != null)
{
boolean xEntrance = maxX > 6 ? (xx > 2 && xx < maxX - 2) : (xx > 1 && xx < maxX - 1);
if (zz == 0 && (this.type.blockEntrance != null && xEntrance))
{
this.setBlockState(worldIn, blockAir, xx, yy, zz, chunkBoundary);
}
else
{
this.setBlockState(worldIn, this.type.blockFloor, xx, yy, zz, chunkBoundary);
}
}
else
{
this.setBlockState(worldIn, blockAir, xx, yy, zz, chunkBoundary);
}
}
}
}
}
return true;
}
/**
* Room contents boundaries are:
* x from 1 to maxX
* y from 1 to this.sizeY - 1
* z from 1 to maxZ
*/
private void buildRoomContents(World worldIn, int x, int y, int z, int maxX, int maxZ, BlockPos blockpos, int randomInt)
{
IBlockState state = Blocks.air.getDefaultState();
int semirand = ((blockpos.getY() * 379 + blockpos.getX()) * 373 + blockpos.getZ()) * 7 & 15;
int facing = 0;
int facing1 = 0;
int facing2 = 0;
int facingLamp = 2;
int facingScreen = 2;
switch (this.direction)
{
case WEST:
facing1 = 3;
facing2 = 2;
facingLamp = 3;
facingScreen = 5;
break;
case EAST:
facing = 2;
facing1 = 1;
facing2 = 0;
facingLamp = 2;
facingScreen = 4;
break;
case NORTH:
facing = 3;
facing1 = 2;
facing2 = 1;
facingLamp = 5;
facingScreen = 2;
break;
case SOUTH:
facing = 1;
facing1 = 0;
facing2 = 3;
facingLamp = 4;
facingScreen = 3;
}
//Offset from centre - used for some rooms
int ox = maxX / 2 - 3;
int xx = x - ox;
switch (this.type)
{
case EMPTY:
//Pillars in corners
if ((z == 1 || z == maxZ - 1) && (x == 2 || x == maxX - 1))
{
state = GCBlocks.wallGC.getStateFromMeta(2);
}
else if (y == 1)
{
//Some random Netherwart
if (semirand < 2)
{
state = AsteroidBlocks.spaceWart.getStateFromMeta(semirand);
}
}
break;
case STORE:
if (maxX >= 6 && y == 1 && maxZ >= 5)
{
//An actual landing pad (indoors!)
if (xx >= 3 && xx <= 5 && z >= 2 && z <= 4)
{
state = GCBlocks.landingPad.getDefaultState();
}
else if (xx == 2)
{
//Cargo loaders and unloaders, these will contain treasure items but only accessible when powered
switch (z)
{
case 2:
state = GCBlocks.cargoLoader.getStateFromMeta(facing);
break;
case 3:
state = GCBlocks.aluminumWire.getStateFromMeta(1);
break;
case 4:
state = GCBlocks.cargoLoader.getStateFromMeta(4 + (facing ^ 2));
break;
default:
}
}
}
break;
case POWER:
facing = (facing + 1) % 4;
switch (y)
{
case 1:
//Layer 1: wall blocks with sealable alu wire in the centre
if (z == 3 && xx >= 4 && x <= maxX - 2) state = GCBlocks.sealableBlock.getStateFromMeta(14);
else if (xx >= 3 && z > 1 && (z < maxZ - 1 || z == 4)) state = this.configuration.getWallBlock();
break;
case 2:
//Layer 2: tier 1 storage and alu wire and a switch
if (z == 2)
{
if (xx == 3) state = GCBlocks.machineTiered.getStateFromMeta(0 + facing);
else if (xx > 3 && x < maxX - 2) state = GCBlocks.aluminumWire.getStateFromMeta(0);
else if (x == maxX - 2) state = GCBlocks.aluminumWire.getStateFromMeta(2);
else if ((xx == 3 || x == maxX - 1)) state = AsteroidBlocks.blockMinerBase.getDefaultState();
}
else if (z == 3 && x == maxX - 2) state = GCBlocks.aluminumWire.getStateFromMeta(0);
//An industrial looking frame for the whole structure
else if (z == 4 && (xx == 3 || x == maxX - 1)) state = AsteroidBlocks.blockMinerBase.getDefaultState();
break;
case 3:
//Layer 3: tier 2 storage and alu wire
if (z == 2 && xx == 4) state = GCBlocks.aluminumWire.getStateFromMeta(0);
else if (z == 3 && x == maxX - 2) state = GCBlocks.machineTiered.getStateFromMeta(8 + (facing ^ 2));
else if (z == 3 && x == maxX - 1) state = GCBlocks.aluminumWire.getStateFromMeta(1);
else if (z == 3 && xx >= 4 && x < maxX - 2) state = GCBlocks.aluminumWire.getStateFromMeta(0);
//An industrial looking frame for the whole structure
else if ((z == 2 || z == 4) && (xx == 3 || x == maxX - 1)) state = AsteroidBlocks.blockMinerBase.getDefaultState();
break;
case 4:
//Layer 4: tier 2 storage and alu wire
if (z == 3)
{
if (x == maxX - 3) state = GCBlocks.machineTiered.getStateFromMeta(8 + facing);
else if (x == maxX - 1 || x == maxX - 2) state = GCBlocks.aluminumWire.getStateFromMeta(1);
}
//An industrial looking frame for the whole structure
else if ((z == 2 || z == 4) && xx >= 3 && x < maxX) state = AsteroidBlocks.blockMinerBase.getDefaultState();
break;
}
break;
case ENGINEERING:
if (y == 1)
{
int closerz = (maxZ <= 5) ? 2 : 3;
if ((z == maxZ - 2 && x == maxX / 2 + 1 || (z == closerz && (x == 2 || x == maxX - 1) && maxX > 5)) && maxZ > 3)
{
state = GCBlocks.nasaWorkbench.getDefaultState();
}
else
{
state = AsteroidBlocks.blockBasic.getStateFromMeta(6);
}
}
break;
case MEDICAL:
int zTable = maxZ - 3;
int zTank = maxZ - 1;
int zLight = zTable;
if (zTable <= 1)
{
if (zTable < 0)
{
//Too small to build the room
break;
}
//Small medical room: bring everything closer together
zTable++;
zLight++;
zTank = maxZ;
}
if (y == 1)
{
//Operating table at y == 1
if (z == zTable && x <= maxX - 1 && x >= maxX - 3)
{
state = GCBlocks.crafting.getStateFromMeta(1);
}
else
//Tiled floor
state = Blocks.iron_trapdoor.getDefaultState();
}
else if (y == 2 || y == 3)
{
//Operating table at y == 2
if (y == 2 && z == zTable && x <= maxX - 1 && x >= maxX - 3)
{
state = GCBlocks.landingPad.getDefaultState();
}
else if (z == zTank)
{
//Fluid tanks, 2 tanks high - these will be filled with Bacterial Sludge below
if ((maxX - x) % 2 == 1)
{
state = GCBlocks.fluidTank.getDefaultState();
}
}
}
else if ((y == 4 || y == 5) && (z == zLight || z == zLight - 1))
{
//Lighting
if (x == maxX)
state = GCBlocks.concealedDetector.getStateFromMeta(8 + facing + (this.configuration.getDeckType() == EnumBaseType.HUMANOID ? 0 : 4));
else if (x == maxX - 1)
state = GCBlocks.brightLamp.getStateFromMeta(facingLamp);
}
break;
case CREW:
if (y == 1)
{
if (x == 2 || x == maxX - 1)
{
if ((z % 2) == 1)
{
state = GCBlocks.wallGC.getStateFromMeta((z == 1) ? 3 : 2);
}
}
else
{
state = Blocks.carpet.getStateFromMeta(7);
}
} else if (y == 2)
{
if (x == 2 || x == maxX - 1)
{
if (z == 1)
{
state = Blocks.brewing_stand.getDefaultState();
}
else if (z > 2 && z < maxZ)
{
state = GCBlocks.landingPad.getStateFromMeta(1);
}
}
}
break;
case CONTROL:
if (y == 1)
{
if (x == maxX / 2 + 1 && z == maxZ - 2)
{
state = AsteroidBlocks.blockBasic.getStateFromMeta(6);
}
else
{
state = GCBlocks.slabGCHalf.getStateFromMeta(6);
}
}
else if (y <= 3)
{
if ((x == 1 || x == maxX) && !(z == 0 || z == maxZ))
{
state = GCBlocks.telemetry.getDefaultState();
}
else if ((x == 2 || x == maxX - 1) && !(z == 0 || z == maxZ))
{
state = GCBlocks.screen.getStateFromMeta((x == 2 ? facingLamp : facingLamp ^ 1));
}
else if (z == maxZ && x > 2 && x < maxX - 1)
{
state = GCBlocks.screen.getStateFromMeta(facingScreen);
}
else if (x == maxX / 2 + 1 && z == maxZ - 2 && y == 2)
{
state = GCBlocks.landingPad.getStateFromMeta(1);
}
}
break;
case CRYO:
boolean xEntrance = maxX > 5 ? (x > 2 && x < maxX - 1) : (x > 1 && x < maxX);
boolean highEntrance = this.configuration.isHangarDeck() && this.configuration.getDeckType() == EnumBaseType.AVIAN;
if (y == 1)
{
//Build a dark plinth for it all at y == 1
if (z == 1 && x > 1 && x < maxX)
{
state = GCBlocks.slabGCHalf.getStateFromMeta(6);
}
else if (z != 0 || !xEntrance || highEntrance)
{
state = AsteroidBlocks.blockBasic.getStateFromMeta(6);
}
}
else if (z == 0 && (y > (highEntrance ? 5 : 3) || !xEntrance))
{
//Dark ceiling and entrance wall
state = AsteroidBlocks.blockBasic.getStateFromMeta(6);
}
else if (y <= 4 && (z == maxZ || x == 1 || x == maxX))
{
//Around the walls: Cryo Chambers alternated with dark blocks
if (z == maxZ && x % 2 == 0 && x < maxX)
{
if (y == 2)
{
state = MarsBlocks.machine.getStateFromMeta(BlockMachineMars.CRYOGENIC_CHAMBER_METADATA + facing1);
}
}
else if (z < maxZ && z > 1 && (maxZ - z) % 2 == 0)
{
if (y == 2)
{
state = MarsBlocks.machine.getStateFromMeta(BlockMachineMars.CRYOGENIC_CHAMBER_METADATA + (x == 1 ? facing : facing2));
}
}
else
{
state = AsteroidBlocks.blockBasic.getStateFromMeta(6);
}
}
else if (y > 5 || y == this.configuration.getRoomHeight() || (z == maxZ || x == 1 || x == maxX))
{
//Dark top section of walls and ceiling
state = AsteroidBlocks.blockBasic.getStateFromMeta(6);
}
break;
default:
}
worldIn.setBlockState(blockpos, state, 2);
if (state.getBlock() instanceof ITileEntityProvider)
{
TileEntity tile = worldIn.getTileEntity(blockpos);
if (tile instanceof IMultiBlock)
{
List<BlockPos> positions = new LinkedList();
((IMultiBlock)tile).getPositions(blockpos, positions);
for (BlockPos pos : positions)
{
worldIn.setBlockState(pos, GCBlocks.fakeBlock.getDefaultState().withProperty(BlockMulti.MULTI_TYPE, ((IMultiBlock)tile).getMultiType()), 2);
}
}
if (tile instanceof TileEntityFluidTank)
{
((TileEntityFluidTank)tile).fill(null, new FluidStack(MarsModule.sludge, 16000), true);
}
else if (tile instanceof TileEntityCargoLoader)
{
TileEntityCargoLoader loader = (TileEntityCargoLoader) tile;
loader.locked = true;
//Looks like the food supplies have gone off!
loader.addCargo(new ItemStack(Items.poisonous_potato, 64, 0), true);
loader.addCargo(new ItemStack(Items.poisonous_potato, 64, 0), true);
loader.addCargo(new ItemStack(Items.poisonous_potato, 64, 0), true);
loader.addCargo(new ItemStack(Items.poisonous_potato, 64, 0), true);
loader.addCargo(new ItemStack(Items.rotten_flesh, 64, 0), true);
loader.addCargo(new ItemStack(GCItems.oilCanister, 1, ItemCanisterGeneric.EMPTY), true);
loader.addCargo(new ItemStack(GCItems.oilCanister, 1, ItemCanisterGeneric.EMPTY), true);
loader.addCargo(new ItemStack(GCItems.oilCanister, 1, ItemCanisterGeneric.EMPTY), true);
loader.addCargo(new ItemStack(GCItems.oilCanister, 1, ItemCanisterGeneric.EMPTY), true);
loader.addCargo(new ItemStack(GCItems.oilCanister, 1, ItemCanisterGeneric.EMPTY), true);
loader.addCargo(new ItemStack(GCItems.oilCanister, 1, ItemCanisterGeneric.EMPTY), true);
loader.addCargo(new ItemStack(GCItems.oilCanister, 1, ItemCanisterGeneric.EMPTY), true);
loader.addCargo(TREASURE1.copy(), true);
loader.addCargo(TREASURE2.copy(), true);
}
else if (tile instanceof TileEntityCrafting)
{
switch (semirand % 4)
{
case 0:
break;
case 1:
((TileEntityCrafting)tile).craftMatrix.setInventorySlotContents(1, new ItemStack(Items.iron_ingot));
((TileEntityCrafting)tile).craftMatrix.setInventorySlotContents(3, new ItemStack(Items.iron_ingot));
break;
case 2:
//Creeper or Zombie head
int slot = semirand % 9;
((TileEntityCrafting)tile).craftMatrix.setInventorySlotContents(slot,new ItemStack(Items.skull, 1, (semirand % 13 < 6) ? 4 : 2));
break;
case 3:
((TileEntityCrafting)tile).craftMatrix.setInventorySlotContents(0, new ItemStack(Items.iron_ingot));
((TileEntityCrafting)tile).craftMatrix.setInventorySlotContents(1, new ItemStack(Items.iron_ingot));
((TileEntityCrafting)tile).craftMatrix.setInventorySlotContents(3, new ItemStack(Items.iron_ingot));
((TileEntityCrafting)tile).craftMatrix.setInventorySlotContents(4, new ItemStack(Items.stick));
((TileEntityCrafting)tile).craftMatrix.setInventorySlotContents(7, new ItemStack(Items.stick));
break;
}
}
else if (tile instanceof TileEntityBrewingStand)
{
TileEntityBrewingStand stand = (TileEntityBrewingStand) tile;
stand.setInventorySlotContents(0, new ItemStack(Items.potionitem, 1, 8196)); //Poison
stand.setInventorySlotContents(1, new ItemStack(Items.potionitem, 1, 8200)); //Weakness
stand.setInventorySlotContents(2, new ItemStack(Items.potionitem, 1, 8204)); //Harming
}
else if (tile instanceof TileEntityEnergyStorageModule)
{
TileEntityEnergyStorageModule store = (TileEntityEnergyStorageModule) tile;
if (semirand % 3 == 1)
{
store.setInventorySlotContents(1, new ItemStack(GCItems.battery, 1, 100));
}
}
}
if (this.type == EnumRoomType.ENGINEERING && y == (this.configuration.getRoomHeight() <= 4 ? 2 : 3) && z == maxZ && (x == 3 || x == 6))
{
EnumFacing hangingDirection = this.direction;
if (hangingDirection == EnumFacing.WEST || hangingDirection == EnumFacing.EAST)
{
//Apparently we have our North and our South reversed ? So we don't want the opposite for North and South!
hangingDirection = hangingDirection.getOpposite();
}
EntityHangingSchematic entityhanging = new EntityHangingSchematic(worldIn, blockpos, hangingDirection, x / 3 - 1);
if (entityhanging != null)
{
worldIn.spawnEntityInWorld(entityhanging);
entityhanging.setSendToClient();
}
}
}
public enum EnumRoomType
{
ENGINEERING(AsteroidBlocks.blockBasic.getStateFromMeta(6), AsteroidBlocks.blockBasic.getStateFromMeta(6), false),
POWER(null, null, false),
STORE(null, null, false),
EMPTY(null, null, false),
MEDICAL(Blocks.iron_trapdoor.getDefaultState(), Blocks.iron_trapdoor.getStateFromMeta(8), false),
CREW(null, null, false),
CRYO(AsteroidBlocks.blockBasic.getStateFromMeta(6), AsteroidBlocks.blockBasic.getStateFromMeta(6), true),
CONTROL(GCBlocks.slabGCHalf.getStateFromMeta(6), AsteroidBlocks.blockBasic.getStateFromMeta(6), false);
public final IBlockState blockFloor;
public final IBlockState blockEntrance;
public final boolean doEntryWallsToo;
EnumRoomType(IBlockState floorBlock, IBlockState entrance, boolean doWalls)
{
this.blockFloor = floorBlock;
this.blockEntrance = entrance;
this.doEntryWallsToo = doWalls;
}
}
}