function hcyl(bottom, height, radius, id) {

	let radsq = radius * radius

	let innerRadsq = (radius - 1.2) * (radius - 1.2)

	height += bottom

	for (let x = -radius; x <= radius; x++) {

		for (let y = bottom; y < height; y++) {

			for (let z = -radius; z <= radius; z++) {

				let d = x * x + z * z

				if (d < radsq && d >= innerRadsq) {

					world.setBlock(p2.x + x, p2.y + y, p2.z + z, id)

				}

			}

		}

	}

}

function cyl(bottom, height, radius, id) {

	let radsq = radius * radius

	height += bottom

	for (let x = -radius; x <= radius; x++) {

		for (let y = bottom; y < height; y++) {

			for (let z = -radius; z <= radius; z++) {

				let d = x * x + z * z

				if (d < radsq) {

					world.setBlock(p2.x + x, p2.y + y, p2.z + z, id)

				}

			}

		}

	}

}

function cube(bottom, height, radius, id) {

	let radsq = radius * radius

	height += bottom

	for (let x = -radius; x <= radius; x++) {

		for (let y = bottom; y < height; y++) {

			for (let z = -radius; z <= radius; z++) {

				let d = x + z

				if (d < radsq) {

					world.setBlock(p2.x + x, p2.y + y, p2.z + z, id)

				}

			}

		}

	}

}

function sphereoid(w, h, d, id) {

	let w2 = w * w

	let h2 = h * h

	let d2 = d * d

	let w3 = (w - 1.5) * (w - 1.5)

	let h3 = (h - 1.5) * (h - 1.5)

	let d3 = (d - 1.5) * (d - 1.5)

	for (let y = -h; y < h; y++) {

		for (let x = -w; x <= w; x++) {

			for (let z = -d; z <= d; z++) {

				let n = x * x / w2 + y * y / h2 + z * z / d2

				let n2 = x * x / w3 + y * y / h3 + z * z / d3

				if (n < 1 && n2 >= 1) {

					world.setBlock(p2.x + x, p2.y + y, p2.z + z, id)

				}

			}

		}

	}

}

function sleep(ms) {

	return new Promise(resolve => setTimeout(() => resolve(), ms))

}

async function asphereoid(w, h, d, id) {

	let px = p2.x

	let py = p2.y

	let pz = p2.z

	let w2 = w * w

	let h2 = h * h

	let d2 = d * d

	let w3 = (w - 1.5) * (w - 1.5)

	let h3 = (h - 1.5) * (h - 1.5)

	let d3 = (d - 1.5) * (d - 1.5)

	for (let y = -h; y < h; y++) {

		for (let x = -w; x <= w; x++) {

			for (let z = -d; z <= d; z++) {

				let n = x * x / w2 + y * y / h2 + z * z / d2

				let n2 = x * x / w3 + y * y / h3 + z * z / d3

				if (n < 1 && n2 >= 1) {

					world.setBlock(px + x, py + y, pz + z, id)

					await sleep(10)

				}

			}

		}

	}

}

function line(x1, y1, z1, x2, y2, z2, id) {

	let dx = Math.abs(x2 - x1);

	let dy = Math.abs(y2 - y1);

	let dz = Math.abs(z2 - z1);

	let sx = (x1 < x2) ? 1 : -1;

	let sy = (y1 < y2) ? 1 : -1;

	let sz = (z1 < z2) ? 1 : -1;

	let err1 = dx - dy;

	let err2 = dx - dz;

	let err3 = dy - dz;

	while (true) {

		world.setBlock(x1, y1, z1, id);

		if (x1 === x2 && y1 === y2 && z1 === z2) break;

		let e2 = 2 * err1;

		let e3 = 2 * err2;

		let e4 = 2 * err3;

		if (e2 > -dy) {

			err1 -= dy;

			err2 -= dz;

			x1 += sx;

		}

		if (e2 < dx) {

			err1 += dx;

			err3 -= dz;

			y1 += sy;

		}

		if (e3 > -dz) {

			err2 += dy;

			err3 += dx;

			z1 += sz;

		}

	}

}

function cloneBlock(sx, sy, sz, dx, dy, dz, w, h, l) {

	for (let x = 0; x < w; x++) {

		for (let y = 0; y < h; y++) {

			for (let z = 0; z < l; z++) {

				let block = world.getBlock(sx + x, sy + y, sz + z);

				world.setBlock(dx + x, dy + y, dz + z, block);

			}

		}

	}

}

function duplicateBlock(sx, sy, sz, dx, dy, dz, w, h, l, offsetX, offsetY, offsetZ, num) {

	for (let i = 0; i < num; i++) {

		cloneBlock(sx, sy, sz, dx + offsetX * i, dy + offsetY * i, dz + offsetZ * i, w, h, l);

	}

}

function rotateBlock(sx, sy, sz, dx, dy, dz, w, h, l, angle) {

	let rad = angle * (Math.PI / 180);

	let sin = Math.sin(rad);

	let cos = Math.cos(rad);

	for (let x = 0; x < w; x++) {

		for (let y = 0; y < h; y++) {

			for (let z = 0; z < l; z++) {

				let nx = Math.round(x * cos - z * sin);

				let nz = Math.round(x * sin + z * cos);

				let block = world.getBlock(sx + x, sy + y, sz + z);

				world.setBlock(dx + nx, dy + y, dz + nz, block);

			}

		}

	}

}

function fillBlock(sx, sy, sz, dx, dy, dz, id) {

	let w = Math.abs(dx - sx) + 1;

	let h = Math.abs(dy - sy) + 1;

	let l = Math.abs(dz - sz) + 1;

	let startX = Math.min(sx, dx);

	let startY = Math.min(sy, dy);

	let startZ = Math.min(sz, dz);

	for (let x = 0; x < w; x++) {

		for (let y = 0; y < h; y++) {

			for (let z = 0; z < l; z++) {

				world.setBlock(startX + x, startY + y, startZ + z, id);

			}

		}

	}

}

function moveBlock(sx, sy, sz, dx, dy, dz, w, h, l) {

	cloneBlock(sx, sy, sz, dx, dy, dz, w, h, l);

	fillBlock(sx, sy, sz, sx + w - 1, sy + h - 1, sz + l - 1, 0);

}

function paintBlock(sx, sy, sz, dx, dy, dz, w, h, l, colorId) {

	cloneBlock(sx, sy, sz, dx, dy, dz, w, h, l);

	for (let x = 0; x < w; x++) {

		for (let y = 0; y < h; y++) {

			for (let z = 0; z < l; z++) {

				world.setBlock(dx + x, dy + y, dz + z, colorId);

			}

		}

	}

}

function replaceBlock(sx, sy, sz, dx, dy, dz, id, newId) {

	let w = Math.abs(dx - sx) + 1;

	let h = Math.abs(dy - sy) + 1;

	let l = Math.abs(dz - sz) + 1;

	let startX = Math.min(sx, dx);

	let startY = Math.min(sy, dy);

	let startZ = Math.min(sz, dz);

	for (let x = 0; x < w; x++) {

		for (let y = 0; y < h; y++) {

			for (let z = 0; z < l; z++) {

				if (world.getBlock(startX + x, startY + y, startZ + z) === id) {

					world.setBlock(startX + x, startY + y, startZ + z, newId);

				}

			}

		}

	}

}

function mirrorBlock(sx, sy, sz, dx, dy, dz, w, h, l, axis) {

	if (axis === "x") {

		for (let x = 0; x < w; x++) {

			for (let y = 0; y < h; y++) {

				for (let z = 0; z < l; z++) {

					let block = world.getBlock(sx + x, sy + y, sz + z);

					world.setBlock(dx + w - x - 1, dy + y, dz + z, block);

				}

			}

		}

	} else if (axis === "y") {

		for (let x = 0; x < w; x++) {

			for (let y = 0; y < h; y++) {

				for (let z = 0; z < l; z++) {

					let block = world.getBlock(sx + x, sy + y, sz + z);

					world.setBlock(dx + x, dy + h - y - 1, dz + z, block);

				}

			}

		}

	} else if (axis === "z") {

		for (let x = 0; x < w; x++) {

			for (let y = 0; y < h; y++) {

				for (let z = 0; z < l; z++) {

					let block = world.getBlock(sx + x, sy + y, sz + z);

					world.setBlock(dx + x, dy + y, dz + l - z - 1, block);

				}

			}

		}

	}

}

function clearBlock(sx, sy, sz, dx, dy, dz) {

	let w = Math.abs(dx - sx) + 1;

	let h = Math.abs(dy - sy) + 1;

	let l = Math.abs(dz - sz) + 1;

	let startX = Math.min(sx, dx);

	let startY = Math.min(sy, dy);

	let startZ = Math.min(sz, dz);

	for (let x = 0; x < w; x++) {

		for (let y = 0; y < h; y++) {

			for (let z = 0; z < l; z++) {

				world.setBlock(startX + x, startY + y, startZ + z, 0);

			}

		}

	}

}

function circleBlock(x, y, z, height, radius, thickness, startDeg, endDeg, id) {

	for (let deg = startDeg; deg <= endDeg; deg++) {

		let rad = deg * (Math.PI / 180);

		let sin = Math.sin(rad);

		let cos = Math.cos(rad);

		for (let h = 0; h < height; h++) {

			for (let r = radius - thickness; r <= radius; r++) {

				let dx = Math.round(r * cos);

				let dz = Math.round(r * sin);

				world.setBlock(x + dx, y + h, z + dz, id);

			}

		}

	}

}

function detectSize(sx, sy, sz, dx, dy, dz) {

	let w = Math.abs(dx - sx) + 1;

	let h = Math.abs(dy - sy) + 1;

	let l = Math.abs(dz - sz) + 1;

	let startX = Math.min(sx, dx);

	let startY = Math.min(sy, dy);

	let startZ = Math.min(sz, dz);

	return {

		width: w,

		height: h,

		length: l

	};

}

function hollowCube(sx, sy, sz, dx, dy, dz, id) {

	let w = Math.abs(dx - sx) + 1;

	let h = Math.abs(dy - sy) + 1;

	let l = Math.abs(dz - sz) + 1;

	let startX = Math.min(sx, dx);

	let startY = Math.min(sy, dy);

	let startZ = Math.min(sz, dz);

	for (let x = 0; x < w; x++) {

		for (let y = 0; y < h; y++) {

			for (let z = 0; z < l; z++) {

				if (x === 0 || x === w - 1 || y === 0 || y === h - 1 || z === 0 || z === l - 1) {

					world.setBlock(startX + x, startY + y, startZ + z, id);

				}

			}

		}

	}

}

function undo() {