package net.minecraft.server;
import com.google.common.collect.ImmutableSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import javax.annotation.Nullable;
public abstract class StructurePiece {
protected static final IBlockData m = Blocks.CAVE_AIR.getBlockData();
protected StructureBoundingBox n;
@Nullable
private EnumDirection a;
private EnumBlockMirror b;
private EnumBlockRotation c;
protected int o;
private final WorldGenFeatureStructurePieceType d;
private static final Set<Block> e = ImmutableSet.builder().add(Blocks.NETHER_BRICK_FENCE).add(Blocks.TORCH).add(Blocks.WALL_TORCH).add(Blocks.OAK_FENCE).add(Blocks.SPRUCE_FENCE).add(Blocks.DARK_OAK_FENCE).add(Blocks.ACACIA_FENCE).add(Blocks.BIRCH_FENCE).add(Blocks.JUNGLE_FENCE).add(Blocks.LADDER).add(Blocks.IRON_BARS).build();
protected StructurePiece(WorldGenFeatureStructurePieceType worldgenfeaturestructurepiecetype, int i) {
this.d = worldgenfeaturestructurepiecetype;
this.o = i;
}
public StructurePiece(WorldGenFeatureStructurePieceType worldgenfeaturestructurepiecetype, NBTTagCompound nbttagcompound) {
this(worldgenfeaturestructurepiecetype, nbttagcompound.getInt("GD"));
if (nbttagcompound.hasKey("BB")) {
this.n = new StructureBoundingBox(nbttagcompound.getIntArray("BB"));
}
int i = nbttagcompound.getInt("O");
this.a(i == -1 ? null : EnumDirection.fromType2(i));
}
public final NBTTagCompound f() {
NBTTagCompound nbttagcompound = new NBTTagCompound();
nbttagcompound.setString("id", IRegistry.STRUCTURE_PIECE.getKey(this.k()).toString());
nbttagcompound.set("BB", this.n.g());
EnumDirection enumdirection = this.i();
nbttagcompound.setInt("O", enumdirection == null ? -1 : enumdirection.get2DRotationValue());
nbttagcompound.setInt("GD", this.o);
this.a(nbttagcompound);
return nbttagcompound;
}
protected abstract void a(NBTTagCompound nbttagcompound);
public void a(StructurePiece structurepiece, List<StructurePiece> list, Random random) {}
public abstract boolean a(GeneratorAccess generatoraccess, ChunkGenerator<?> chunkgenerator, Random random, StructureBoundingBox structureboundingbox, ChunkCoordIntPair chunkcoordintpair);
public StructureBoundingBox g() {
return this.n;
}
public int h() {
return this.o;
}
public boolean a(ChunkCoordIntPair chunkcoordintpair, int i) {
int j = chunkcoordintpair.x << 4;
int k = chunkcoordintpair.z << 4;
return this.n.a(j - i, k - i, j + 15 + i, k + 15 + i);
}
public static StructurePiece a(List<StructurePiece> list, StructureBoundingBox structureboundingbox) {
Iterator iterator = list.iterator();
StructurePiece structurepiece;
do {
if (!iterator.hasNext()) {
return null;
}
structurepiece = (StructurePiece) iterator.next();
} while (structurepiece.g() == null || !structurepiece.g().b(structureboundingbox));
return structurepiece;
}
protected boolean a(IBlockAccess iblockaccess, StructureBoundingBox structureboundingbox) {
int i = Math.max(this.n.a - 1, structureboundingbox.a);
int j = Math.max(this.n.b - 1, structureboundingbox.b);
int k = Math.max(this.n.c - 1, structureboundingbox.c);
int l = Math.min(this.n.d + 1, structureboundingbox.d);
int i1 = Math.min(this.n.e + 1, structureboundingbox.e);
int j1 = Math.min(this.n.f + 1, structureboundingbox.f);
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
int k1;
int l1;
for (k1 = i; k1 <= l; ++k1) {
for (l1 = k; l1 <= j1; ++l1) {
if (iblockaccess.getType(blockposition_mutableblockposition.d(k1, j, l1)).getMaterial().isLiquid()) {
return true;
}
if (iblockaccess.getType(blockposition_mutableblockposition.d(k1, i1, l1)).getMaterial().isLiquid()) {
return true;
}
}
}
for (k1 = i; k1 <= l; ++k1) {
for (l1 = j; l1 <= i1; ++l1) {
if (iblockaccess.getType(blockposition_mutableblockposition.d(k1, l1, k)).getMaterial().isLiquid()) {
return true;
}
if (iblockaccess.getType(blockposition_mutableblockposition.d(k1, l1, j1)).getMaterial().isLiquid()) {
return true;
}
}
}
for (k1 = k; k1 <= j1; ++k1) {
for (l1 = j; l1 <= i1; ++l1) {
if (iblockaccess.getType(blockposition_mutableblockposition.d(i, l1, k1)).getMaterial().isLiquid()) {
return true;
}
if (iblockaccess.getType(blockposition_mutableblockposition.d(l, l1, k1)).getMaterial().isLiquid()) {
return true;
}
}
}
return false;
}
protected int a(int i, int j) {
EnumDirection enumdirection = this.i();
if (enumdirection == null) {
return i;
} else {
switch (enumdirection) {
case NORTH:
case SOUTH:
return this.n.a + i;
case WEST:
return this.n.d - j;
case EAST:
return this.n.a + j;
default:
return i;
}
}
}
protected int d(int i) {
return this.i() == null ? i : i + this.n.b;
}
protected int b(int i, int j) {
EnumDirection enumdirection = this.i();
if (enumdirection == null) {
return j;
} else {
switch (enumdirection) {
case NORTH:
return this.n.f - j;
case SOUTH:
return this.n.c + j;
case WEST:
case EAST:
return this.n.c + i;
default:
return j;
}
}
}
protected void a(GeneratorAccess generatoraccess, IBlockData iblockdata, int i, int j, int k, StructureBoundingBox structureboundingbox) {
BlockPosition blockposition = new BlockPosition(this.a(i, k), this.d(j), this.b(i, k));
if (structureboundingbox.b((BaseBlockPosition) blockposition)) {
if (this.b != EnumBlockMirror.NONE) {
iblockdata = iblockdata.a(this.b);
}
if (this.c != EnumBlockRotation.NONE) {
iblockdata = iblockdata.a(this.c);
}
generatoraccess.setTypeAndData(blockposition, iblockdata, 2);
Fluid fluid = generatoraccess.getFluid(blockposition);
if (!fluid.isEmpty()) {
generatoraccess.getFluidTickList().a(blockposition, fluid.getType(), 0);
}
if (StructurePiece.e.contains(iblockdata.getBlock())) {
generatoraccess.x(blockposition).e(blockposition);
}
}
}
protected IBlockData a(IBlockAccess iblockaccess, int i, int j, int k, StructureBoundingBox structureboundingbox) {
int l = this.a(i, k);
int i1 = this.d(j);
int j1 = this.b(i, k);
BlockPosition blockposition = new BlockPosition(l, i1, j1);
return !structureboundingbox.b((BaseBlockPosition) blockposition) ? Blocks.AIR.getBlockData() : iblockaccess.getType(blockposition);
}
protected boolean a(IWorldReader iworldreader, int i, int j, int k, StructureBoundingBox structureboundingbox) {
int l = this.a(i, k);
int i1 = this.d(j + 1);
int j1 = this.b(i, k);
BlockPosition blockposition = new BlockPosition(l, i1, j1);
return !structureboundingbox.b((BaseBlockPosition) blockposition) ? false : i1 < iworldreader.a(HeightMap.Type.OCEAN_FLOOR_WG, l, j1);
}
protected void b(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, int i, int j, int k, int l, int i1, int j1) {
for (int k1 = j; k1 <= i1; ++k1) {
for (int l1 = i; l1 <= l; ++l1) {
for (int i2 = k; i2 <= j1; ++i2) {
this.a(generatoraccess, Blocks.AIR.getBlockData(), l1, k1, i2, structureboundingbox);
}
}
}
}
protected void a(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, int i, int j, int k, int l, int i1, int j1, IBlockData iblockdata, IBlockData iblockdata1, boolean flag) {
for (int k1 = j; k1 <= i1; ++k1) {
for (int l1 = i; l1 <= l; ++l1) {
for (int i2 = k; i2 <= j1; ++i2) {
if (!flag || !this.a((IBlockAccess) generatoraccess, l1, k1, i2, structureboundingbox).isAir()) {
if (k1 != j && k1 != i1 && l1 != i && l1 != l && i2 != k && i2 != j1) {
this.a(generatoraccess, iblockdata1, l1, k1, i2, structureboundingbox);
} else {
this.a(generatoraccess, iblockdata, l1, k1, i2, structureboundingbox);
}
}
}
}
}
}
protected void a(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, int i, int j, int k, int l, int i1, int j1, boolean flag, Random random, StructurePiece.StructurePieceBlockSelector structurepiece_structurepieceblockselector) {
for (int k1 = j; k1 <= i1; ++k1) {
for (int l1 = i; l1 <= l; ++l1) {
for (int i2 = k; i2 <= j1; ++i2) {
if (!flag || !this.a((IBlockAccess) generatoraccess, l1, k1, i2, structureboundingbox).isAir()) {
structurepiece_structurepieceblockselector.a(random, l1, k1, i2, k1 == j || k1 == i1 || l1 == i || l1 == l || i2 == k || i2 == j1);
this.a(generatoraccess, structurepiece_structurepieceblockselector.a(), l1, k1, i2, structureboundingbox);
}
}
}
}
}
protected void a(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, Random random, float f, int i, int j, int k, int l, int i1, int j1, IBlockData iblockdata, IBlockData iblockdata1, boolean flag, boolean flag1) {
for (int k1 = j; k1 <= i1; ++k1) {
for (int l1 = i; l1 <= l; ++l1) {
for (int i2 = k; i2 <= j1; ++i2) {
if (random.nextFloat() <= f && (!flag || !this.a((IBlockAccess) generatoraccess, l1, k1, i2, structureboundingbox).isAir()) && (!flag1 || this.a((IWorldReader) generatoraccess, l1, k1, i2, structureboundingbox))) {
if (k1 != j && k1 != i1 && l1 != i && l1 != l && i2 != k && i2 != j1) {
this.a(generatoraccess, iblockdata1, l1, k1, i2, structureboundingbox);
} else {
this.a(generatoraccess, iblockdata, l1, k1, i2, structureboundingbox);
}
}
}
}
}
}
protected void a(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, Random random, float f, int i, int j, int k, IBlockData iblockdata) {
if (random.nextFloat() < f) {
this.a(generatoraccess, iblockdata, i, j, k, structureboundingbox);
}
}
protected void a(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, int i, int j, int k, int l, int i1, int j1, IBlockData iblockdata, boolean flag) {
float f = (float) (l - i + 1);
float f1 = (float) (i1 - j + 1);
float f2 = (float) (j1 - k + 1);
float f3 = (float) i + f / 2.0F;
float f4 = (float) k + f2 / 2.0F;
for (int k1 = j; k1 <= i1; ++k1) {
float f5 = (float) (k1 - j) / f1;
for (int l1 = i; l1 <= l; ++l1) {
float f6 = ((float) l1 - f3) / (f * 0.5F);
for (int i2 = k; i2 <= j1; ++i2) {
float f7 = ((float) i2 - f4) / (f2 * 0.5F);
if (!flag || !this.a((IBlockAccess) generatoraccess, l1, k1, i2, structureboundingbox).isAir()) {
float f8 = f6 * f6 + f5 * f5 + f7 * f7;
if (f8 <= 1.05F) {
this.a(generatoraccess, iblockdata, l1, k1, i2, structureboundingbox);
}
}
}
}
}
}
protected void b(GeneratorAccess generatoraccess, IBlockData iblockdata, int i, int j, int k, StructureBoundingBox structureboundingbox) {
int l = this.a(i, k);
int i1 = this.d(j);
int j1 = this.b(i, k);
if (structureboundingbox.b((BaseBlockPosition) (new BlockPosition(l, i1, j1)))) {
while ((generatoraccess.isEmpty(new BlockPosition(l, i1, j1)) || generatoraccess.getType(new BlockPosition(l, i1, j1)).getMaterial().isLiquid()) && i1 > 1) {
generatoraccess.setTypeAndData(new BlockPosition(l, i1, j1), iblockdata, 2);
--i1;
}
}
}
protected boolean a(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, Random random, int i, int j, int k, MinecraftKey minecraftkey) {
BlockPosition blockposition = new BlockPosition(this.a(i, k), this.d(j), this.b(i, k));
return this.a(generatoraccess, structureboundingbox, random, blockposition, minecraftkey, (IBlockData) null);
}
public static IBlockData a(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata) {
EnumDirection enumdirection = null;
Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator();
while (iterator.hasNext()) {
EnumDirection enumdirection1 = (EnumDirection) iterator.next();
BlockPosition blockposition1 = blockposition.shift(enumdirection1);
IBlockData iblockdata1 = iblockaccess.getType(blockposition1);
if (iblockdata1.getBlock() == Blocks.CHEST) {
return iblockdata;
}
if (iblockdata1.g(iblockaccess, blockposition1)) {
if (enumdirection != null) {
enumdirection = null;
break;
}
enumdirection = enumdirection1;
}
}
if (enumdirection != null) {
return (IBlockData) iblockdata.set(BlockFacingHorizontal.FACING, enumdirection.opposite());
} else {
EnumDirection enumdirection2 = (EnumDirection) iblockdata.get(BlockFacingHorizontal.FACING);
BlockPosition blockposition2 = blockposition.shift(enumdirection2);
if (iblockaccess.getType(blockposition2).g(iblockaccess, blockposition2)) {
enumdirection2 = enumdirection2.opposite();
blockposition2 = blockposition.shift(enumdirection2);
}
if (iblockaccess.getType(blockposition2).g(iblockaccess, blockposition2)) {
enumdirection2 = enumdirection2.f();
blockposition2 = blockposition.shift(enumdirection2);
}
if (iblockaccess.getType(blockposition2).g(iblockaccess, blockposition2)) {
enumdirection2 = enumdirection2.opposite();
blockposition.shift(enumdirection2);
}
return (IBlockData) iblockdata.set(BlockFacingHorizontal.FACING, enumdirection2);
}
}
protected boolean a(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, Random random, BlockPosition blockposition, MinecraftKey minecraftkey, @Nullable IBlockData iblockdata) {
if (structureboundingbox.b((BaseBlockPosition) blockposition) && generatoraccess.getType(blockposition).getBlock() != Blocks.CHEST) {
if (iblockdata == null) {
iblockdata = a((IBlockAccess) generatoraccess, blockposition, Blocks.CHEST.getBlockData());
}
generatoraccess.setTypeAndData(blockposition, iblockdata, 2);
TileEntity tileentity = generatoraccess.getTileEntity(blockposition);
if (tileentity instanceof TileEntityChest) {
((TileEntityChest) tileentity).setLootTable(minecraftkey, random.nextLong());
}
return true;
} else {
return false;
}
}
protected boolean a(GeneratorAccess generatoraccess, StructureBoundingBox structureboundingbox, Random random, int i, int j, int k, EnumDirection enumdirection, MinecraftKey minecraftkey) {
BlockPosition blockposition = new BlockPosition(this.a(i, k), this.d(j), this.b(i, k));
if (structureboundingbox.b((BaseBlockPosition) blockposition) && generatoraccess.getType(blockposition).getBlock() != Blocks.DISPENSER) {
this.a(generatoraccess, (IBlockData) Blocks.DISPENSER.getBlockData().set(BlockDispenser.FACING, enumdirection), i, j, k, structureboundingbox);
TileEntity tileentity = generatoraccess.getTileEntity(blockposition);
if (tileentity instanceof TileEntityDispenser) {
((TileEntityDispenser) tileentity).setLootTable(minecraftkey, random.nextLong());
}
return true;
} else {
return false;
}
}
public void a(int i, int j, int k) {
this.n.a(i, j, k);
}
@Nullable
public EnumDirection i() {
return this.a;
}
public void a(@Nullable EnumDirection enumdirection) {
this.a = enumdirection;
if (enumdirection == null) {
this.c = EnumBlockRotation.NONE;
this.b = EnumBlockMirror.NONE;
} else {
switch (enumdirection) {
case SOUTH:
this.b = EnumBlockMirror.LEFT_RIGHT;
this.c = EnumBlockRotation.NONE;
break;
case WEST:
this.b = EnumBlockMirror.LEFT_RIGHT;
this.c = EnumBlockRotation.CLOCKWISE_90;
break;
case EAST:
this.b = EnumBlockMirror.NONE;
this.c = EnumBlockRotation.CLOCKWISE_90;
break;
default:
this.b = EnumBlockMirror.NONE;
this.c = EnumBlockRotation.NONE;
}
}
}
public EnumBlockRotation ad_() {
return this.c;
}
public WorldGenFeatureStructurePieceType k() {
return this.d;
}
public abstract static class StructurePieceBlockSelector {
protected IBlockData a;
protected StructurePieceBlockSelector() {
this.a = Blocks.AIR.getBlockData();
}
public abstract void a(Random random, int i, int j, int k, boolean flag);
public IBlockData a() {
return this.a;
}
}
}