use of org.pepsoft.minecraft.Block in project WorldPainter by Captain-Chaos.
the class WPObjectExporter method isRoom.
/**
* Checks block by block and taking the object's collision mode attributes
* and other rules into account whether it can be placed at a particular
* location. This is a slow operation, so use
* {@link #isSane(WPObject, int, int, int, int)} first to weed out objects
* for which this check does not even apply.
*
* @return <code>true</code> if the object may be placed at the specified
* location according to its collision mode attributes.
*/
public static boolean isRoom(final MinecraftWorld world, final Dimension dimension, final WPObject object, final int x, final int y, final int z, final Placement placement) {
final Point3i dimensions = object.getDimensions();
final Point3i offset = object.getOffset();
final int collisionMode = object.getAttribute(ATTRIBUTE_COLLISION_MODE), maxHeight = world.getMaxHeight();
final boolean allowConnectingBlocks = false, bottomlessWorld = dimension.isBottomless();
// Check if the object fits vertically
if (((long) z + dimensions.z - 1 + offset.z) >= world.getMaxHeight()) {
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " because it does not fit below the map height of " + world.getMaxHeight());
}
return false;
}
if (((long) z + dimensions.z - 1 + offset.z) < 0) {
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " because it is entirely below the bedrock");
}
return false;
}
if ((placement == Placement.ON_LAND) && (collisionMode != COLLISION_MODE_NONE)) {
// Check block by block whether there is room
for (int dx = 0; dx < dimensions.x; dx++) {
for (int dy = 0; dy < dimensions.y; dy++) {
final int worldX = x + dx + offset.x, worldY = y + dy + offset.y;
for (int dz = 0; dz < dimensions.z; dz++) {
if (object.getMask(dx, dy, dz)) {
final Block objectBlock = object.getMaterial(dx, dy, dz).block;
if (!objectBlock.veryInsubstantial) {
final int worldZ = z + dz + offset.z;
if (worldZ < (bottomlessWorld ? 0 : 1)) {
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " because it extends below the bottom of the map");
}
return false;
} else if (worldZ >= maxHeight) {
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " because it extends above the top of the map");
}
return false;
} else if (worldZ > dimension.getIntHeightAt(worldX, worldY)) {
if ((collisionMode == COLLISION_MODE_ALL) ? (!AIR_AND_FLUIDS.contains(world.getBlockTypeAt(worldX, worldY, worldZ))) : (!BLOCKS[world.getBlockTypeAt(worldX, worldY, worldZ)].veryInsubstantial)) {
// there is no room for this object
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " due to collision with existing above ground block of type " + BLOCKS[world.getBlockTypeAt(worldX, worldY, worldZ)]);
}
return false;
} else if ((!allowConnectingBlocks) && wouldConnect(world, worldX, worldY, worldZ, objectBlock.id)) {
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " because it would cause a connecting block");
}
return false;
}
}
}
}
}
}
}
} else if (placement == Placement.FLOATING) {
// with the floor
for (int dx = 0; dx < dimensions.x; dx++) {
for (int dy = 0; dy < dimensions.y; dy++) {
final int worldX = x + dx + offset.x, worldY = y + dy + offset.y;
final int terrainHeight = dimension.getIntHeightAt(worldX, worldY);
for (int dz = 0; dz < dimensions.z; dz++) {
if (object.getMask(dx, dy, dz)) {
final Block objectBlock = object.getMaterial(dx, dy, dz).block;
if (!objectBlock.veryInsubstantial) {
final int worldZ = z + dz + offset.z;
if (worldZ < (bottomlessWorld ? 0 : 1)) {
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " because it extends below the bottom of the map");
}
return false;
} else if (worldZ >= maxHeight) {
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " because it extends above the top of the map");
}
return false;
} else if (worldZ <= terrainHeight) {
// the floor
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " due to collision with floor");
}
return false;
} else if (collisionMode != COLLISION_MODE_NONE) {
if ((collisionMode == COLLISION_MODE_ALL) ? (!AIR_AND_FLUIDS.contains(world.getBlockTypeAt(worldX, worldY, worldZ))) : (!BLOCKS[world.getBlockTypeAt(worldX, worldY, worldZ)].veryInsubstantial)) {
// world; there is no room for this object
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " due to collision with existing above ground block of type " + BLOCK_TYPE_NAMES[world.getBlockTypeAt(worldX, worldY, worldZ)]);
}
return false;
} else if ((!allowConnectingBlocks) && wouldConnect(world, worldX, worldY, worldZ, objectBlock.id)) {
if (logger.isTraceEnabled()) {
logger.trace("No room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement + " because it would cause a connecting block");
}
return false;
}
}
}
}
}
}
}
}
if (logger.isTraceEnabled()) {
logger.trace("There is room for object " + object.getName() + " @ " + x + "," + y + "," + z + " with placement " + placement);
}
return true;
}